diff --git a/.github/workflows/research-regression-tests.yml b/.github/workflows/research-regression-tests.yml
index e4cf0f7497db..b13d6e6065b6 100644
--- a/.github/workflows/research-regression-tests.yml
+++ b/.github/workflows/research-regression-tests.yml
@@ -28,9 +28,9 @@ jobs:
shell: bash
run: |
# install dependencies
- pip3 install papermill==2.4.0 clr-loader==0.1.6
+ pip3 install papermill==2.4.0 clr-loader==0.2.9
# install kernel
- dotnet tool install --global Microsoft.dotnet-interactive --version 1.0.607001
+ dotnet tool install -g --no-cache --version 1.0.661703 --add-source "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json" Microsoft.dotnet-interactive
# Add dotnet tools to Path
export PATH="$HOME/.dotnet/tools:$PATH"
# activate kernel for jupyter
diff --git a/Algorithm.CSharp/AddAndRemoveOptionContractRegressionAlgorithm.cs b/Algorithm.CSharp/AddAndRemoveOptionContractRegressionAlgorithm.cs
index 452439dc65ed..77e9bb89f315 100644
--- a/Algorithm.CSharp/AddAndRemoveOptionContractRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/AddAndRemoveOptionContractRegressionAlgorithm.cs
@@ -87,7 +87,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 24;
+ public long DataPoints => 26;
///
/// Data Points count of the algorithm history
diff --git a/Algorithm.CSharp/AddAndRemoveSecuritySameLoopRegressionAlgorithm.cs b/Algorithm.CSharp/AddAndRemoveSecuritySameLoopRegressionAlgorithm.cs
index 2c864924deee..017718215175 100644
--- a/Algorithm.CSharp/AddAndRemoveSecuritySameLoopRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/AddAndRemoveSecuritySameLoopRegressionAlgorithm.cs
@@ -82,7 +82,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 24;
+ public long DataPoints => 25;
///
/// Data Points count of the algorithm history
diff --git a/Algorithm.CSharp/AddBetaIndicatorNewAssetsRegressionAlgorithm.cs b/Algorithm.CSharp/AddBetaIndicatorNewAssetsRegressionAlgorithm.cs
index f9020dfd7406..213ab2824913 100644
--- a/Algorithm.CSharp/AddBetaIndicatorNewAssetsRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/AddBetaIndicatorNewAssetsRegressionAlgorithm.cs
@@ -1,11 +1,11 @@
/*
* 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");
+ *
+ * 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.
@@ -107,7 +107,7 @@ public override void OnOrderEvent(OrderEvent orderEvent)
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 77;
+ public int AlgorithmHistoryDataPoints => 26;
///
/// Final status of the algorithm
@@ -122,18 +122,18 @@ public override void OnOrderEvent(OrderEvent orderEvent)
{"Total Orders", "436"},
{"Average Win", "0.28%"},
{"Average Loss", "-0.01%"},
- {"Compounding Annual Return", "1.926%"},
+ {"Compounding Annual Return", "1.925%"},
{"Drawdown", "1.000%"},
- {"Expectancy", "1.650"},
+ {"Expectancy", "1.649"},
{"Start Equity", "10000.00"},
- {"End Equity", "10411.11"},
- {"Net Profit", "4.111%"},
+ {"End Equity", "10410.99"},
+ {"Net Profit", "4.110%"},
{"Sharpe Ratio", "0.332"},
{"Sortino Ratio", "0.313"},
{"Probabilistic Sharpe Ratio", "74.084%"},
{"Loss Rate", "90%"},
{"Win Rate", "10%"},
- {"Profit-Loss Ratio", "25.26"},
+ {"Profit-Loss Ratio", "25.25"},
{"Alpha", "0.003"},
{"Beta", "0.001"},
{"Annual Standard Deviation", "0.01"},
@@ -146,7 +146,7 @@ public override void OnOrderEvent(OrderEvent orderEvent)
{"Lowest Capacity Asset", "BTCUSD 2XR"},
{"Portfolio Turnover", "2.22%"},
{"Drawdown Recovery", "139"},
- {"OrderListHash", "9fce77ef8817cf0159897fc64d01f5e9"}
+ {"OrderListHash", "896ecc92440d51ed26644aac5b8706e4"}
};
}
}
diff --git a/Algorithm.CSharp/AddFutureContractWithContinuousRegressionAlgorithm.cs b/Algorithm.CSharp/AddFutureContractWithContinuousRegressionAlgorithm.cs
index 5bd61eecd005..4267b57aefcf 100644
--- a/Algorithm.CSharp/AddFutureContractWithContinuousRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/AddFutureContractWithContinuousRegressionAlgorithm.cs
@@ -132,34 +132,34 @@ public override void OnSecuritiesChanged(SecurityChanges changes)
///
public Dictionary ExpectedStatistics => new Dictionary
{
- {"Total Orders", "3"},
+ {"Total Orders", "4"},
{"Average Win", "0%"},
- {"Average Loss", "-0.03%"},
- {"Compounding Annual Return", "-2.594%"},
- {"Drawdown", "0.000%"},
+ {"Average Loss", "-0.10%"},
+ {"Compounding Annual Return", "-14.232%"},
+ {"Drawdown", "0.200%"},
{"Expectancy", "-1"},
{"Start Equity", "100000"},
- {"End Equity", "99966.4"},
- {"Net Profit", "-0.034%"},
- {"Sharpe Ratio", "-10.666"},
+ {"End Equity", "99803.9"},
+ {"Net Profit", "-0.196%"},
+ {"Sharpe Ratio", "-7.95"},
{"Sortino Ratio", "0"},
{"Probabilistic Sharpe Ratio", "1.216%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
- {"Alpha", "-0.029"},
- {"Beta", "0.004"},
- {"Annual Standard Deviation", "0.003"},
+ {"Alpha", "-0.128"},
+ {"Beta", "0.026"},
+ {"Annual Standard Deviation", "0.016"},
{"Annual Variance", "0"},
- {"Information Ratio", "-0.768"},
- {"Tracking Error", "0.241"},
- {"Treynor Ratio", "-6.368"},
+ {"Information Ratio", "-1.186"},
+ {"Tracking Error", "0.237"},
+ {"Treynor Ratio", "-4.747"},
{"Total Fees", "$8.60"},
- {"Estimated Strategy Capacity", "$5500000.00"},
- {"Lowest Capacity Asset", "ES VMKLFZIH2MTD"},
- {"Portfolio Turnover", "66.80%"},
+ {"Estimated Strategy Capacity", "$2000.00"},
+ {"Lowest Capacity Asset", "ES VU1EHIDJYLMP"},
+ {"Portfolio Turnover", "66.50%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "39f1e15c27212d8fdd58aeb7fb2b93cc"}
+ {"OrderListHash", "4720516462fcabb4db1aead46051cb4a"}
};
}
}
diff --git a/Algorithm.CSharp/AddFutureOptionContractFromFutureChainRegressionAlgorithm.cs b/Algorithm.CSharp/AddFutureOptionContractFromFutureChainRegressionAlgorithm.cs
index c27639ebe074..68c7554e0b68 100644
--- a/Algorithm.CSharp/AddFutureOptionContractFromFutureChainRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/AddFutureOptionContractFromFutureChainRegressionAlgorithm.cs
@@ -134,10 +134,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "68696.045"},
{"Total Fees", "$35.70"},
{"Estimated Strategy Capacity", "$2600000.00"},
- {"Lowest Capacity Asset", "ES 31C3JQS9D84PW|ES XCZJLC9NOB29"},
+ {"Lowest Capacity Asset", "ES 31C3JQS9DCF1G|ES XCZJLC9NOB29"},
{"Portfolio Turnover", "495.15%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "85257286f088992d599c1ad0799a6237"}
+ {"OrderListHash", "af830085995d0b8fa0d33a6e80dd1241"}
};
}
}
diff --git a/Algorithm.CSharp/AddFutureOptionSingleOptionChainSelectedInUniverseFilterRegressionAlgorithm.cs b/Algorithm.CSharp/AddFutureOptionSingleOptionChainSelectedInUniverseFilterRegressionAlgorithm.cs
index 0add96b829d3..feae130a33c6 100644
--- a/Algorithm.CSharp/AddFutureOptionSingleOptionChainSelectedInUniverseFilterRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/AddFutureOptionSingleOptionChainSelectedInUniverseFilterRegressionAlgorithm.cs
@@ -240,31 +240,31 @@ public override void OnEndOfAlgorithm()
{"Total Orders", "2"},
{"Average Win", "0%"},
{"Average Loss", "0%"},
- {"Compounding Annual Return", "309.669%"},
- {"Drawdown", "0.900%"},
+ {"Compounding Annual Return", "430.834%"},
+ {"Drawdown", "4.200%"},
{"Expectancy", "0"},
{"Start Equity", "100000"},
- {"End Equity", "101950.53"},
- {"Net Profit", "1.951%"},
- {"Sharpe Ratio", "15.402"},
+ {"End Equity", "102313.03"},
+ {"Net Profit", "2.313%"},
+ {"Sharpe Ratio", "17.721"},
{"Sortino Ratio", "0"},
{"Probabilistic Sharpe Ratio", "95.977%"},
{"Loss Rate", "0%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
- {"Alpha", "1.886"},
- {"Beta", "1.066"},
- {"Annual Standard Deviation", "0.155"},
- {"Annual Variance", "0.024"},
- {"Information Ratio", "13.528"},
- {"Tracking Error", "0.142"},
- {"Treynor Ratio", "2.237"},
+ {"Alpha", "2.663"},
+ {"Beta", "1.264"},
+ {"Annual Standard Deviation", "0.184"},
+ {"Annual Variance", "0.034"},
+ {"Information Ratio", "16.514"},
+ {"Tracking Error", "0.169"},
+ {"Treynor Ratio", "2.574"},
{"Total Fees", "$3.57"},
- {"Estimated Strategy Capacity", "$760000.00"},
- {"Lowest Capacity Asset", "ES XCZJLDQX2SRO|ES XCZJLC9NOB29"},
- {"Portfolio Turnover", "32.31%"},
+ {"Estimated Strategy Capacity", "$28000000.00"},
+ {"Lowest Capacity Asset", "ES XCZJLCA62LNO|ES XCZJLC9NOB29"},
+ {"Portfolio Turnover", "33.84%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "7a04f66a30d793bf187c2695781ad3ee"}
+ {"OrderListHash", "7c82013ecabca41591e0253a477025dd"}
};
}
}
diff --git a/Algorithm.CSharp/AddOptionContractExpiresRegressionAlgorithm.cs b/Algorithm.CSharp/AddOptionContractExpiresRegressionAlgorithm.cs
index 2de16c4662d0..7b3cd2e256d5 100644
--- a/Algorithm.CSharp/AddOptionContractExpiresRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/AddOptionContractExpiresRegressionAlgorithm.cs
@@ -117,7 +117,7 @@ public override void OnData(Slice slice)
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 37597;
+ public long DataPoints => 37598;
///
/// Data Points count of the algorithm history
@@ -158,10 +158,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "2.01"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$5700000.00"},
- {"Lowest Capacity Asset", "AOL VRKS95ENLBYE|AOL R735QTJ8XC9X"},
+ {"Lowest Capacity Asset", "AOL VRKS95ENPM9Y|AOL R735QTJ8XC9X"},
{"Portfolio Turnover", "0.55%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "fc5ab25181a01ca5ce39212f60eb0ecd"}
+ {"OrderListHash", "d314aef81752b6583fd58f9e49054cd4"}
};
}
}
diff --git a/Algorithm.CSharp/AddOptionContractFromUniverseRegressionAlgorithm.cs b/Algorithm.CSharp/AddOptionContractFromUniverseRegressionAlgorithm.cs
index b4f121be3a51..deca83e88107 100644
--- a/Algorithm.CSharp/AddOptionContractFromUniverseRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/AddOptionContractFromUniverseRegressionAlgorithm.cs
@@ -169,7 +169,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 5798;
+ public long DataPoints => 5800;
///
/// Data Points count of the algorithm history
@@ -210,10 +210,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "0.335"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$2800000.00"},
- {"Lowest Capacity Asset", "AOL VRKS95ENLBYE|AOL R735QTJ8XC9X"},
+ {"Lowest Capacity Asset", "AOL VRKS95ENPM9Y|AOL R735QTJ8XC9X"},
{"Portfolio Turnover", "1.14%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "90aa4bf345a6ba5ea2b0b14e32d1598f"}
+ {"OrderListHash", "e33b98d8e94ed92d0441fc6fe0d461fb"}
};
}
}
diff --git a/Algorithm.CSharp/AddOptionContractTwiceRegressionAlgorithm.cs b/Algorithm.CSharp/AddOptionContractTwiceRegressionAlgorithm.cs
index 5454bfde232f..15fec4905e3d 100644
--- a/Algorithm.CSharp/AddOptionContractTwiceRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/AddOptionContractTwiceRegressionAlgorithm.cs
@@ -116,7 +116,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 3814;
+ public long DataPoints => 3818;
///
/// Data Points count of the algorithm history
@@ -157,10 +157,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "0"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$5000000.00"},
- {"Lowest Capacity Asset", "AAPL VXBK4R62CXGM|AAPL R735QTJ8XC9X"},
+ {"Lowest Capacity Asset", "AAPL VXBK4R62H7S6|AAPL R735QTJ8XC9X"},
{"Portfolio Turnover", "22.70%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "29fd1b75f6db05dd823a6db7e8bd90a9"}
+ {"OrderListHash", "71511e4929377cd55fbf5e7e9555c248"}
};
}
}
diff --git a/Algorithm.CSharp/AddOptionUniverseSelectionModelRegressionAlgorithm.cs b/Algorithm.CSharp/AddOptionUniverseSelectionModelRegressionAlgorithm.cs
index a38ef57cad4b..06dedcaa057a 100644
--- a/Algorithm.CSharp/AddOptionUniverseSelectionModelRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/AddOptionUniverseSelectionModelRegressionAlgorithm.cs
@@ -96,7 +96,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 1658167;
+ public long DataPoints => 2349547;
///
/// Data Points count of the algorithm history
diff --git a/Algorithm.CSharp/AddRemoveOptionUniverseRegressionAlgorithm.cs b/Algorithm.CSharp/AddRemoveOptionUniverseRegressionAlgorithm.cs
index e056c3329ecd..d10fb7f61d80 100644
--- a/Algorithm.CSharp/AddRemoveOptionUniverseRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/AddRemoveOptionUniverseRegressionAlgorithm.cs
@@ -246,10 +246,10 @@ public override void OnSecuritiesChanged(SecurityChanges changes)
{"Treynor Ratio", "0"},
{"Total Fees", "$6.00"},
{"Estimated Strategy Capacity", "$4000.00"},
- {"Lowest Capacity Asset", "GOOCV 305RBQ2BZBZT2|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 305RBQ2BZGA4M|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "2.58%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "12037c87de17d6e62eadd99c70a0685e"}
+ {"OrderListHash", "f418de0673fc166487daf80991dfe3a0"}
};
}
}
diff --git a/Algorithm.CSharp/AddRemoveSecurityCacheRegressionAlgorithm.cs b/Algorithm.CSharp/AddRemoveSecurityCacheRegressionAlgorithm.cs
index ed9084e175a0..673e7081c3f5 100644
--- a/Algorithm.CSharp/AddRemoveSecurityCacheRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/AddRemoveSecurityCacheRegressionAlgorithm.cs
@@ -83,7 +83,7 @@ public override void OnData(Slice slice)
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 11202;
+ public long DataPoints => 15042;
///
/// Data Points count of the algorithm history
diff --git a/Algorithm.CSharp/AddRemoveSecurityRegressionAlgorithm.cs b/Algorithm.CSharp/AddRemoveSecurityRegressionAlgorithm.cs
index b76f3478181b..ecb9cbd519b1 100644
--- a/Algorithm.CSharp/AddRemoveSecurityRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/AddRemoveSecurityRegressionAlgorithm.cs
@@ -110,7 +110,7 @@ public override void OnOrderEvent(OrderEvent orderEvent)
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 7063;
+ public long DataPoints => 7065;
///
/// Data Points count of the algorithm history
diff --git a/Algorithm.CSharp/AddTwoAndRemoveOneOptionContractRegressionAlgorithm.cs b/Algorithm.CSharp/AddTwoAndRemoveOneOptionContractRegressionAlgorithm.cs
index 0f6a0d0af28e..7d1807b35b3c 100644
--- a/Algorithm.CSharp/AddTwoAndRemoveOneOptionContractRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/AddTwoAndRemoveOneOptionContractRegressionAlgorithm.cs
@@ -101,7 +101,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 1578;
+ public long DataPoints => 1579;
///
/// Data Points count of the algorithm history
@@ -142,10 +142,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "0"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$6200000.00"},
- {"Lowest Capacity Asset", "AAPL VXBK4QA5EM92|AAPL R735QTJ8XC9X"},
+ {"Lowest Capacity Asset", "AAPL VXBK4QA5IWKM|AAPL R735QTJ8XC9X"},
{"Portfolio Turnover", "90.27%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "a111609c2c64554268539b5798e5b31f"}
+ {"OrderListHash", "a332b93ff5e2dfe89258c450a64c7125"}
};
}
}
diff --git a/Algorithm.CSharp/AutomaticIndicatorWarmupDataTypeRegressionAlgorithm.cs b/Algorithm.CSharp/AutomaticIndicatorWarmupDataTypeRegressionAlgorithm.cs
index d6eddc5c1a6f..f6633f164a02 100644
--- a/Algorithm.CSharp/AutomaticIndicatorWarmupDataTypeRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/AutomaticIndicatorWarmupDataTypeRegressionAlgorithm.cs
@@ -38,7 +38,7 @@ public override void Initialize()
SetEndDate(2013, 10, 10);
var SP500 = QuantConnect.Symbol.Create(Futures.Indices.SP500EMini, SecurityType.Future, Market.CME);
- _symbol = FuturesChain(SP500).First();
+ _symbol = FuturesChain(SP500).OrderBy(x => x.Symbol.ID.Date).First();
// Test case: custom IndicatorBase indicator using Future unsubscribed symbol
var indicator1 = new CustomIndicator();
diff --git a/Algorithm.CSharp/AutomaticSeedBaseRegressionAlgorithm.cs b/Algorithm.CSharp/AutomaticSeedBaseRegressionAlgorithm.cs
new file mode 100644
index 000000000000..a39b4c19f68e
--- /dev/null
+++ b/Algorithm.CSharp/AutomaticSeedBaseRegressionAlgorithm.cs
@@ -0,0 +1,137 @@
+/*
+ * 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 System.Linq;
+using QuantConnect.Interfaces;
+using QuantConnect.Data.UniverseSelection;
+using QuantConnect.Data.Market;
+using QuantConnect.Securities;
+
+namespace QuantConnect.Algorithm.CSharp
+{
+ ///
+ /// Regression algorithm asserting that security are automatically seeded by default
+ ///
+ public abstract class AutomaticSeedBaseRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
+ {
+ protected virtual bool ShouldHaveTradeData { get; }
+ protected virtual bool ShouldHaveQuoteData { get; }
+ protected virtual bool ShouldHaveOpenInterestData { get; }
+
+ public override void OnSecuritiesChanged(SecurityChanges changes)
+ {
+ var gotTrades = false;
+ var gotQuotes = false;
+ var gotOpenInterest = false;
+
+ foreach (var addedSecurity in changes.AddedSecurities.Where(x => !x.Symbol.IsCanonical() || x.Symbol.SecurityType == SecurityType.Future))
+ {
+ if (addedSecurity.Price == 0)
+ {
+ throw new RegressionTestException("Security was not seeded");
+ }
+
+ if (!addedSecurity.HasData)
+ {
+ throw new RegressionTestException("Security does not have TradeBar or QuoteBar or OpenInterest data");
+ }
+
+ gotTrades |= addedSecurity.Cache.GetData() != null;
+ gotQuotes |= addedSecurity.Cache.GetData() != null;
+ gotOpenInterest |= addedSecurity.Cache.GetData() != null;
+ }
+
+ if (changes.AddedSecurities.Count > 0)
+ {
+ if (ShouldHaveTradeData && !gotTrades)
+ {
+ throw new RegressionTestException("No contract had TradeBar data");
+ }
+
+ if (ShouldHaveQuoteData && !gotQuotes)
+ {
+ throw new RegressionTestException("No contract had QuoteBar data");
+ }
+
+ if (ShouldHaveOpenInterestData && !gotOpenInterest)
+ {
+ throw new RegressionTestException("No contract had OpenInterest 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 abstract long DataPoints { get; }
+
+ ///
+ /// Data Points count of the algorithm history
+ ///
+ public abstract int AlgorithmHistoryDataPoints { get; }
+
+ ///
+ /// 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 virtual 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", "0"},
+ {"Tracking Error", "0"},
+ {"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/AuxiliaryDataHandlersRegressionAlgorithm.cs b/Algorithm.CSharp/AuxiliaryDataHandlersRegressionAlgorithm.cs
index 2ec3d8eac6a3..26b22be5da87 100644
--- a/Algorithm.CSharp/AuxiliaryDataHandlersRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/AuxiliaryDataHandlersRegressionAlgorithm.cs
@@ -119,7 +119,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 126221;
+ public long DataPoints => 126222;
///
/// Data Points count of the algorithm history
diff --git a/Algorithm.CSharp/BacktestingBrokerageRegressionAlgorithm.cs b/Algorithm.CSharp/BacktestingBrokerageRegressionAlgorithm.cs
index 458818cbd35d..57fb83f684cc 100644
--- a/Algorithm.CSharp/BacktestingBrokerageRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/BacktestingBrokerageRegressionAlgorithm.cs
@@ -340,7 +340,7 @@ public override OrderEvent MarketFill(Security asset, MarketOrder order)
{"Lowest Capacity Asset", "GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "17.02%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "a7ce5ff2bbe0fe273cf1631ea5a73fa6"}
+ {"OrderListHash", "1be5073f2cf8802ffa163f7dab7d040e"}
};
}
}
diff --git a/Algorithm.CSharp/BasicSetAccountCurrencyAlgorithm.cs b/Algorithm.CSharp/BasicSetAccountCurrencyAlgorithm.cs
index b32816e5483e..12a2a95a6a52 100644
--- a/Algorithm.CSharp/BasicSetAccountCurrencyAlgorithm.cs
+++ b/Algorithm.CSharp/BasicSetAccountCurrencyAlgorithm.cs
@@ -77,7 +77,7 @@ public override void OnData(Slice slice)
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 120;
+ public int AlgorithmHistoryDataPoints => 15;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/BasicSetAccountCurrencyWithAmountAlgorithm.cs b/Algorithm.CSharp/BasicSetAccountCurrencyWithAmountAlgorithm.cs
index def5fcfcb173..039ccaec651a 100644
--- a/Algorithm.CSharp/BasicSetAccountCurrencyWithAmountAlgorithm.cs
+++ b/Algorithm.CSharp/BasicSetAccountCurrencyWithAmountAlgorithm.cs
@@ -47,7 +47,7 @@ public override void SetAccountCurrency()
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 120;
+ public int AlgorithmHistoryDataPoints => 15;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/BasicTemplateCryptoAlgorithm.cs b/Algorithm.CSharp/BasicTemplateCryptoAlgorithm.cs
index 4268d083e60c..5c3ce2f2c90d 100644
--- a/Algorithm.CSharp/BasicTemplateCryptoAlgorithm.cs
+++ b/Algorithm.CSharp/BasicTemplateCryptoAlgorithm.cs
@@ -202,7 +202,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 240;
+ public int AlgorithmHistoryDataPoints => 35;
///
/// Final status of the algorithm
@@ -220,7 +220,7 @@ public override void OnEndOfAlgorithm()
{"Compounding Annual Return", "0%"},
{"Drawdown", "0%"},
{"Expectancy", "0"},
- {"Start Equity", "31588.24"},
+ {"Start Equity", "31592.84"},
{"End Equity", "30866.71"},
{"Net Profit", "0%"},
{"Sharpe Ratio", "0"},
diff --git a/Algorithm.CSharp/BasicTemplateFuturesAlgorithm.cs b/Algorithm.CSharp/BasicTemplateFuturesAlgorithm.cs
index 7299325651c0..8bb42742ea27 100644
--- a/Algorithm.CSharp/BasicTemplateFuturesAlgorithm.cs
+++ b/Algorithm.CSharp/BasicTemplateFuturesAlgorithm.cs
@@ -154,7 +154,7 @@ public override void OnSecuritiesChanged(SecurityChanges changes)
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 340;
+ public int AlgorithmHistoryDataPoints => 354;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/BasicTemplateFuturesDailyAlgorithm.cs b/Algorithm.CSharp/BasicTemplateFuturesDailyAlgorithm.cs
index 2706e4c9e63b..f974b487d57d 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 => 5861;
+ public virtual long DataPoints => 5867;
///
/// Data Points count of the algorithm history
@@ -144,34 +144,34 @@ public override void OnSecuritiesChanged(SecurityChanges changes)
///
public virtual Dictionary ExpectedStatistics => new Dictionary
{
- {"Total Orders", "34"},
+ {"Total Orders", "38"},
{"Average Win", "0.33%"},
- {"Average Loss", "-0.04%"},
- {"Compounding Annual Return", "0.106%"},
+ {"Average Loss", "-0.03%"},
+ {"Compounding Annual Return", "0.098%"},
{"Drawdown", "0.300%"},
- {"Expectancy", "0.178"},
+ {"Expectancy", "0.165"},
{"Start Equity", "1000000"},
- {"End Equity", "1001066.2"},
- {"Net Profit", "0.107%"},
- {"Sharpe Ratio", "-1.695"},
- {"Sortino Ratio", "-0.804"},
- {"Probabilistic Sharpe Ratio", "14.797%"},
- {"Loss Rate", "88%"},
- {"Win Rate", "12%"},
- {"Profit-Loss Ratio", "9.01"},
+ {"End Equity", "1000991.96"},
+ {"Net Profit", "0.099%"},
+ {"Sharpe Ratio", "-1.708"},
+ {"Sortino Ratio", "-0.84"},
+ {"Probabilistic Sharpe Ratio", "14.542%"},
+ {"Loss Rate", "89%"},
+ {"Win Rate", "11%"},
+ {"Profit-Loss Ratio", "10.07"},
{"Alpha", "-0.007"},
{"Beta", "0.002"},
{"Annual Standard Deviation", "0.004"},
{"Annual Variance", "0"},
- {"Information Ratio", "-1.353"},
+ {"Information Ratio", "-1.354"},
{"Tracking Error", "0.089"},
- {"Treynor Ratio", "-4.112"},
- {"Total Fees", "$76.30"},
+ {"Treynor Ratio", "-4.054"},
+ {"Total Fees", "$85.54"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", "ES VRJST036ZY0X"},
- {"Portfolio Turnover", "0.92%"},
+ {"Portfolio Turnover", "1.04%"},
{"Drawdown Recovery", "69"},
- {"OrderListHash", "ddaa9dd20647fdbc4811d6e64bb30a40"}
+ {"OrderListHash", "eafc33ea4dcb219f7aacdbdd0973d5bc"}
};
}
}
diff --git a/Algorithm.CSharp/BasicTemplateFuturesHourlyAlgorithm.cs b/Algorithm.CSharp/BasicTemplateFuturesHourlyAlgorithm.cs
index aeceacdfd9c1..7315cc7d6b90 100644
--- a/Algorithm.CSharp/BasicTemplateFuturesHourlyAlgorithm.cs
+++ b/Algorithm.CSharp/BasicTemplateFuturesHourlyAlgorithm.cs
@@ -36,7 +36,7 @@ public class BasicTemplateFuturesHourlyAlgorithm : BasicTemplateFuturesDailyAlgo
///
/// Data Points count of all timeslices of algorithm
///
- public override long DataPoints => 25312;
+ public override long DataPoints => 25339;
///
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
@@ -70,7 +70,7 @@ public class BasicTemplateFuturesHourlyAlgorithm : BasicTemplateFuturesDailyAlgo
{"Lowest Capacity Asset", "ES VP274HSU1AF5"},
{"Portfolio Turnover", "20.14%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "f6482c8757f82cb9f4c058e3ed6bc494"}
+ {"OrderListHash", "c301a0a086f8905b1a555f0257087272"}
};
}
}
diff --git a/Algorithm.CSharp/BasicTemplateFuturesWithExtendedMarketAlgorithm.cs b/Algorithm.CSharp/BasicTemplateFuturesWithExtendedMarketAlgorithm.cs
index f3323557cadd..693c63a7cd56 100644
--- a/Algorithm.CSharp/BasicTemplateFuturesWithExtendedMarketAlgorithm.cs
+++ b/Algorithm.CSharp/BasicTemplateFuturesWithExtendedMarketAlgorithm.cs
@@ -154,7 +154,7 @@ public override void OnSecuritiesChanged(SecurityChanges changes)
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 340;
+ public int AlgorithmHistoryDataPoints => 354;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/BasicTemplateFuturesWithExtendedMarketDailyAlgorithm.cs b/Algorithm.CSharp/BasicTemplateFuturesWithExtendedMarketDailyAlgorithm.cs
index ab16ebf797f9..1c4e76a60095 100644
--- a/Algorithm.CSharp/BasicTemplateFuturesWithExtendedMarketDailyAlgorithm.cs
+++ b/Algorithm.CSharp/BasicTemplateFuturesWithExtendedMarketDailyAlgorithm.cs
@@ -36,41 +36,41 @@ public class BasicTemplateFuturesWithExtendedMarketDailyAlgorithm : BasicTemplat
///
/// Data Points count of all timeslices of algorithm
///
- public override long DataPoints => 5965;
+ public override long DataPoints => 5971;
///
/// 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", "32"},
+ {"Total Orders", "36"},
{"Average Win", "0.33%"},
- {"Average Loss", "-0.04%"},
- {"Compounding Annual Return", "0.110%"},
+ {"Average Loss", "-0.03%"},
+ {"Compounding Annual Return", "0.103%"},
{"Drawdown", "0.300%"},
- {"Expectancy", "0.184"},
+ {"Expectancy", "0.172"},
{"Start Equity", "1000000"},
- {"End Equity", "1001108"},
- {"Net Profit", "0.111%"},
- {"Sharpe Ratio", "-1.688"},
- {"Sortino Ratio", "-0.772"},
- {"Probabilistic Sharpe Ratio", "14.944%"},
- {"Loss Rate", "88%"},
- {"Win Rate", "12%"},
- {"Profit-Loss Ratio", "8.47"},
+ {"End Equity", "1001033.76"},
+ {"Net Profit", "0.103%"},
+ {"Sharpe Ratio", "-1.701"},
+ {"Sortino Ratio", "-0.809"},
+ {"Probabilistic Sharpe Ratio", "14.685%"},
+ {"Loss Rate", "89%"},
+ {"Win Rate", "11%"},
+ {"Profit-Loss Ratio", "9.55"},
{"Alpha", "-0.007"},
{"Beta", "0.002"},
{"Annual Standard Deviation", "0.004"},
{"Annual Variance", "0"},
{"Information Ratio", "-1.353"},
{"Tracking Error", "0.089"},
- {"Treynor Ratio", "-4.099"},
- {"Total Fees", "$72.00"},
+ {"Treynor Ratio", "-4.042"},
+ {"Total Fees", "$81.24"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", "ES VRJST036ZY0X"},
- {"Portfolio Turnover", "0.87%"},
+ {"Portfolio Turnover", "0.99%"},
{"Drawdown Recovery", "69"},
- {"OrderListHash", "741a26424d2210171ad849d92fc75d23"}
+ {"OrderListHash", "67120ad5c9a6116001dda6c8061e5353"}
};
}
}
diff --git a/Algorithm.CSharp/BasicTemplateFuturesWithExtendedMarketHourlyAlgorithm.cs b/Algorithm.CSharp/BasicTemplateFuturesWithExtendedMarketHourlyAlgorithm.cs
index 3e2bd74e5694..89ac65c85714 100644
--- a/Algorithm.CSharp/BasicTemplateFuturesWithExtendedMarketHourlyAlgorithm.cs
+++ b/Algorithm.CSharp/BasicTemplateFuturesWithExtendedMarketHourlyAlgorithm.cs
@@ -41,7 +41,7 @@ public class BasicTemplateFuturesWithExtendedMarketHourlyAlgorithm : BasicTempla
///
/// Data Points count of all timeslices of algorithm
///
- public override long DataPoints => 67924;
+ public override long DataPoints => 67998;
///
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
diff --git a/Algorithm.CSharp/BasicTemplateIndexAlgorithm.cs b/Algorithm.CSharp/BasicTemplateIndexAlgorithm.cs
index da2f7a2ba14b..debaeb04cf9c 100644
--- a/Algorithm.CSharp/BasicTemplateIndexAlgorithm.cs
+++ b/Algorithm.CSharp/BasicTemplateIndexAlgorithm.cs
@@ -168,10 +168,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "-1.771"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$3000.00"},
- {"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
+ {"Lowest Capacity Asset", "SPX XL80P3GHIA9A|SPX 31"},
{"Portfolio Turnover", "23.97%"},
{"Drawdown Recovery", "9"},
- {"OrderListHash", "51f1bc2ea080df79748dc66c2520b782"}
+ {"OrderListHash", "4b560d2a8cfae510c3c8dc92603470fc"}
};
}
}
diff --git a/Algorithm.CSharp/BasicTemplateIndexDailyAlgorithm.cs b/Algorithm.CSharp/BasicTemplateIndexDailyAlgorithm.cs
index 1839b7d4e303..44a783d0a7f8 100644
--- a/Algorithm.CSharp/BasicTemplateIndexDailyAlgorithm.cs
+++ b/Algorithm.CSharp/BasicTemplateIndexDailyAlgorithm.cs
@@ -147,10 +147,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "-6.937"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
- {"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
+ {"Lowest Capacity Asset", "SPX XL80P3GHIA9A|SPX 31"},
{"Portfolio Turnover", "2.42%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "61e8517ac3da6bed414ef23d26736fef"}
+ {"OrderListHash", "ce421d0aeb7bde3bc92a6b87c09c510e"}
};
}
}
diff --git a/Algorithm.CSharp/BasicTemplateIndexHourlyAlgorithm.cs b/Algorithm.CSharp/BasicTemplateIndexHourlyAlgorithm.cs
index 0b930443b1ac..f0770bd9878a 100644
--- a/Algorithm.CSharp/BasicTemplateIndexHourlyAlgorithm.cs
+++ b/Algorithm.CSharp/BasicTemplateIndexHourlyAlgorithm.cs
@@ -64,10 +64,10 @@ public class BasicTemplateIndexHourlyAlgorithm : BasicTemplateIndexDailyAlgorith
{"Treynor Ratio", "-6.189"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$300000.00"},
- {"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
+ {"Lowest Capacity Asset", "SPX XL80P3GHIA9A|SPX 31"},
{"Portfolio Turnover", "24.63%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "5595ab834c2584c1d124ad575e88cc1a"}
+ {"OrderListHash", "7bc05310e971f09b0663bc380fdfee80"}
};
}
}
diff --git a/Algorithm.CSharp/BasicTemplateIndexOptionsDailyAlgorithm.cs b/Algorithm.CSharp/BasicTemplateIndexOptionsDailyAlgorithm.cs
index 2e1104681c5b..130e9dcbaa36 100644
--- a/Algorithm.CSharp/BasicTemplateIndexOptionsDailyAlgorithm.cs
+++ b/Algorithm.CSharp/BasicTemplateIndexOptionsDailyAlgorithm.cs
@@ -108,10 +108,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "-44.954"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
- {"Lowest Capacity Asset", "SPX XL80P59H5E6M|SPX 31"},
+ {"Lowest Capacity Asset", "SPX XL80P59H9OI6|SPX 31"},
{"Portfolio Turnover", "0.00%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "8340619d603921c1ce261287890b9c1c"}
+ {"OrderListHash", "34d295b82e29b1dbe8f104d3300d9255"}
};
}
}
diff --git a/Algorithm.CSharp/BasicTemplateIndexOptionsHourlyAlgorithm.cs b/Algorithm.CSharp/BasicTemplateIndexOptionsHourlyAlgorithm.cs
index f418209945d2..8584b5c09753 100644
--- a/Algorithm.CSharp/BasicTemplateIndexOptionsHourlyAlgorithm.cs
+++ b/Algorithm.CSharp/BasicTemplateIndexOptionsHourlyAlgorithm.cs
@@ -79,10 +79,10 @@ public class BasicTemplateIndexOptionsHourlyAlgorithm : BasicTemplateIndexOption
{"Treynor Ratio", "116.921"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
- {"Lowest Capacity Asset", "SPX XL80P59H5E6M|SPX 31"},
+ {"Lowest Capacity Asset", "SPX XL80P59H9OI6|SPX 31"},
{"Portfolio Turnover", "0.00%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "1c5f424cfe62777733ee68a20320bb8d"}
+ {"OrderListHash", "214026660a13ecaecc7074fa97f86ea1"}
};
}
}
diff --git a/Algorithm.CSharp/BasicTemplateOptionEquityStrategyAlgorithm.cs b/Algorithm.CSharp/BasicTemplateOptionEquityStrategyAlgorithm.cs
index 05895c5d1f9d..fb6107525c59 100644
--- a/Algorithm.CSharp/BasicTemplateOptionEquityStrategyAlgorithm.cs
+++ b/Algorithm.CSharp/BasicTemplateOptionEquityStrategyAlgorithm.cs
@@ -44,7 +44,7 @@ public override void Initialize()
_optionSymbol = option.Symbol;
// set our strike/expiry filter for this option chain
- option.SetFilter(u => u.Strikes(-2, +2)
+ option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2)
// Expiration method accepts TimeSpan objects or integer for days.
// The following statements yield the same filtering criteria
.Expiration(0, 180));
@@ -73,7 +73,7 @@ public override void OnData(Slice slice)
var higherStrike = callContracts[2].Strike;
var optionStrategy = OptionStrategies.CallButterfly(_optionSymbol, higherStrike, middleStrike, lowerStrike, expiry);
-
+
Order(optionStrategy, 10);
}
}
@@ -143,10 +143,10 @@ public override void OnOrderEvent(OrderEvent orderEvent)
{"Treynor Ratio", "0"},
{"Total Fees", "$26.00"},
{"Estimated Strategy Capacity", "$69000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZERHAT67A|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "61.31%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "35d406df401e5b27244e20f5ec57346e"}
+ {"OrderListHash", "ccd6cb1b6244d0c6d30b2760938958f1"}
};
}
}
diff --git a/Algorithm.CSharp/BasicTemplateOptionStrategyAlgorithm.cs b/Algorithm.CSharp/BasicTemplateOptionStrategyAlgorithm.cs
index c5b45fe0ca18..56e35003743d 100644
--- a/Algorithm.CSharp/BasicTemplateOptionStrategyAlgorithm.cs
+++ b/Algorithm.CSharp/BasicTemplateOptionStrategyAlgorithm.cs
@@ -50,8 +50,9 @@ public override void Initialize()
// set our strike/expiry filter for this option chain
// SetFilter method accepts TimeSpan objects or integer for days.
// The following statements yield the same filtering criteria
- option.SetFilter(-2, +2, 0, 180);
- // option.SetFilter(-2, +2, TimeSpan.Zero, TimeSpan.FromDays(180));
+ option.SetFilter(u => u.StandardsOnly()
+ .Strikes(-2, +2)
+ .Expiration(0, 180));
// Adding this to reproduce GH issue #2314
SetWarmup(TimeSpan.FromMinutes(1));
@@ -83,7 +84,7 @@ public override void OnData(Slice slice)
Liquidate();
}
- foreach(var kpv in slice.Bars)
+ foreach (var kpv in slice.Bars)
{
Log($"---> OnData: {Time}, {kpv.Key.Value}, {kpv.Value.Close:0.00}");
}
@@ -153,10 +154,10 @@ public override void OnOrderEvent(OrderEvent orderEvent)
{"Treynor Ratio", "0"},
{"Total Fees", "$543.40"},
{"Estimated Strategy Capacity", "$4000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZFMEBBB2E|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZFMEBFLDY|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "338.60%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "301c15063f6e269023d144ca69a765da"}
+ {"OrderListHash", "8229716b93428dc885cf856b4cc9fc35"}
};
}
}
diff --git a/Algorithm.CSharp/BasicTemplateOptionsAlgorithm.cs b/Algorithm.CSharp/BasicTemplateOptionsAlgorithm.cs
index 059e24cc9a66..c5b8950f617b 100644
--- a/Algorithm.CSharp/BasicTemplateOptionsAlgorithm.cs
+++ b/Algorithm.CSharp/BasicTemplateOptionsAlgorithm.cs
@@ -48,11 +48,10 @@ public override void Initialize()
_optionSymbol = option.Symbol;
// set our strike/expiry filter for this option chain
- option.SetFilter(u => u.Strikes(-2, +2)
+ option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2)
// Expiration method accepts TimeSpan objects or integer for days.
// The following statements yield the same filtering criteria
- .Expiration(0, 180));
- // .Expiration(TimeSpan.Zero, TimeSpan.FromDays(180)));
+ .Expiration(0, 180)); // .Expiration(TimeSpan.Zero, TimeSpan.FromDays(180)));
// use the underlying equity as the benchmark
SetBenchmark(equity.Symbol);
@@ -150,10 +149,10 @@ public override void OnOrderEvent(OrderEvent orderEvent)
{"Treynor Ratio", "0"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$1300000.00"},
- {"Lowest Capacity Asset", "GOOCV 30AKMEIPOSS1Y|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 30AKMEIPOX2DI|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "10.71%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "8a36462ee0349c04d01d464e592dd347"}
+ {"OrderListHash", "19ba1220073493495880581b38df2da9"}
};
}
}
diff --git a/Algorithm.CSharp/BasicTemplateOptionsDailyAlgorithm.cs b/Algorithm.CSharp/BasicTemplateOptionsDailyAlgorithm.cs
index 9a048a9df069..b6b1f61c6a51 100644
--- a/Algorithm.CSharp/BasicTemplateOptionsDailyAlgorithm.cs
+++ b/Algorithm.CSharp/BasicTemplateOptionsDailyAlgorithm.cs
@@ -163,10 +163,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "-3.212"},
{"Total Fees", "$1.00"},
{"Estimated Strategy Capacity", "$72000.00"},
- {"Lowest Capacity Asset", "AAPL W78ZEO2985GM|AAPL R735QTJ8XC9X"},
+ {"Lowest Capacity Asset", "AAPL W78ZEO29CFS6|AAPL R735QTJ8XC9X"},
{"Portfolio Turnover", "0.02%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "5e20fad3461ac9998afe8d76ad43b25c"}
+ {"OrderListHash", "5639c19a7d56ec312f61029b943903b8"}
};
}
}
diff --git a/Algorithm.CSharp/BasicTemplateOptionsFilterUniverseAlgorithm.cs b/Algorithm.CSharp/BasicTemplateOptionsFilterUniverseAlgorithm.cs
index 9daf2616b3db..4950cff1c710 100644
--- a/Algorithm.CSharp/BasicTemplateOptionsFilterUniverseAlgorithm.cs
+++ b/Algorithm.CSharp/BasicTemplateOptionsFilterUniverseAlgorithm.cs
@@ -143,7 +143,7 @@ public override void OnOrderEvent(OrderEvent orderEvent)
{"Lowest Capacity Asset", "GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "15.08%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "f68f6d64a5721ee148bc3c643f8d1b7f"}
+ {"OrderListHash", "c53bc9318676161ed3b7797c945e2113"}
};
}
}
diff --git a/Algorithm.CSharp/BasicTemplateOptionsFrameworkAlgorithm.cs b/Algorithm.CSharp/BasicTemplateOptionsFrameworkAlgorithm.cs
index ea842ab17ee1..5b17aa867192 100644
--- a/Algorithm.CSharp/BasicTemplateOptionsFrameworkAlgorithm.cs
+++ b/Algorithm.CSharp/BasicTemplateOptionsFrameworkAlgorithm.cs
@@ -139,7 +139,7 @@ public override IEnumerable CreateTargets(QCAlgorithm algorith
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 17486;
+ public long DataPoints => 17487;
///
/// Data Points count of the algorithm history
@@ -183,7 +183,7 @@ public override IEnumerable CreateTargets(QCAlgorithm algorith
{"Lowest Capacity Asset", "AAPL R735QTJ8XC9X"},
{"Portfolio Turnover", "13.50%"},
{"Drawdown Recovery", "2"},
- {"OrderListHash", "d40c84371facba5dac8a2c919ea75807"}
+ {"OrderListHash", "2ab4ffc0944a2888a3be0568c2570a79"}
};
}
}
diff --git a/Algorithm.CSharp/BasicTemplateOptionsHourlyAlgorithm.cs b/Algorithm.CSharp/BasicTemplateOptionsHourlyAlgorithm.cs
index 882d82d9294b..5a16c668ae43 100644
--- a/Algorithm.CSharp/BasicTemplateOptionsHourlyAlgorithm.cs
+++ b/Algorithm.CSharp/BasicTemplateOptionsHourlyAlgorithm.cs
@@ -48,7 +48,7 @@ public override void Initialize()
_optionSymbol = option.Symbol;
// set our strike/expiry filter for this option chain
- option.SetFilter(u => u.Strikes(-2, +2)
+ option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2)
// Expiration method accepts TimeSpan objects or integer for days.
// The following statements yield the same filtering criteria
.Expiration(0, 180));
@@ -150,10 +150,10 @@ public override void OnOrderEvent(OrderEvent orderEvent)
{"Treynor Ratio", "1.434"},
{"Total Fees", "$4.00"},
{"Estimated Strategy Capacity", "$1000.00"},
- {"Lowest Capacity Asset", "AAPL 2ZTXYMUAHCIAU|AAPL R735QTJ8XC9X"},
+ {"Lowest Capacity Asset", "AAPL 2ZTXYMUAHGSME|AAPL R735QTJ8XC9X"},
{"Portfolio Turnover", "2.28%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "7804b3dcf20d3096a2265a289fa81cd3"}
+ {"OrderListHash", "70bbc60c969f18e943e8e00cf0f7a0ea"}
};
}
}
diff --git a/Algorithm.CSharp/BasicTemplateSPXWeeklyIndexOptionsAlgorithm.cs b/Algorithm.CSharp/BasicTemplateSPXWeeklyIndexOptionsAlgorithm.cs
index 6d3fb41d9010..a9b121363b77 100644
--- a/Algorithm.CSharp/BasicTemplateSPXWeeklyIndexOptionsAlgorithm.cs
+++ b/Algorithm.CSharp/BasicTemplateSPXWeeklyIndexOptionsAlgorithm.cs
@@ -144,10 +144,10 @@ public override void OnOrderEvent(OrderEvent orderEvent)
{"Treynor Ratio", "-0.725"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$580000.00"},
- {"Lowest Capacity Asset", "SPXW 31K54PVWHUJHQ|SPX 31"},
+ {"Lowest Capacity Asset", "SPXW 31K54PVWHYTTA|SPX 31"},
{"Portfolio Turnover", "0.40%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "db5e3681c5fa1888262f2370a9b14c11"}
+ {"OrderListHash", "03148bbb5453fc1056a3285bd31ce158"}
};
}
}
diff --git a/Algorithm.CSharp/BasicTemplateSPXWeeklyIndexOptionsStrategyAlgorithm.cs b/Algorithm.CSharp/BasicTemplateSPXWeeklyIndexOptionsStrategyAlgorithm.cs
index e52b07e15ced..01cc595854ed 100644
--- a/Algorithm.CSharp/BasicTemplateSPXWeeklyIndexOptionsStrategyAlgorithm.cs
+++ b/Algorithm.CSharp/BasicTemplateSPXWeeklyIndexOptionsStrategyAlgorithm.cs
@@ -150,10 +150,10 @@ public override void OnOrderEvent(OrderEvent orderEvent)
{"Treynor Ratio", "0.589"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$13000000.00"},
- {"Lowest Capacity Asset", "SPXW XKX6S2GM9PGU|SPX 31"},
+ {"Lowest Capacity Asset", "SPXW XKX6S2GMDZSE|SPX 31"},
{"Portfolio Turnover", "0.28%"},
{"Drawdown Recovery", "2"},
- {"OrderListHash", "17764ae9e216d003b1f3ce68d15b68ef"}
+ {"OrderListHash", "9d03f85003416861df07ccb31a18af9a"}
};
}
}
diff --git a/Algorithm.CSharp/BasicTemplateTradableIndexAlgorithm.cs b/Algorithm.CSharp/BasicTemplateTradableIndexAlgorithm.cs
index 4dfa61e47926..fd2b14693819 100644
--- a/Algorithm.CSharp/BasicTemplateTradableIndexAlgorithm.cs
+++ b/Algorithm.CSharp/BasicTemplateTradableIndexAlgorithm.cs
@@ -87,10 +87,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "-1.771"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$3000.00"},
- {"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
+ {"Lowest Capacity Asset", "SPX XL80P3GHIA9A|SPX 31"},
{"Portfolio Turnover", "24.03%"},
{"Drawdown Recovery", "9"},
- {"OrderListHash", "fcd6fddb0a315e21095c2b35eb633e2b"}
+ {"OrderListHash", "691cf4990024b856a0a70255c9fd2545"}
};
}
}
diff --git a/Algorithm.CSharp/Benchmarks/EmptySPXOptionChainBenchmark.cs b/Algorithm.CSharp/Benchmarks/EmptySPXOptionChainBenchmark.cs
new file mode 100644
index 000000000000..74a2f08881f3
--- /dev/null
+++ b/Algorithm.CSharp/Benchmarks/EmptySPXOptionChainBenchmark.cs
@@ -0,0 +1,34 @@
+/*
+ * 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.
+*/
+
+namespace QuantConnect.Algorithm.CSharp.Benchmarks
+{
+ ///
+ /// Benchmark Algorithm that adds SPX option chain but does not trade it.
+ /// This is an interesting benchmark because SPX option chains are large
+ ///
+ public class EmptySPXOptionChainBenchmark : QCAlgorithm
+ {
+ public override void Initialize()
+ {
+ SetStartDate(2018, 1, 1);
+ SetEndDate(2020, 6, 1);
+
+ var index = AddIndex("SPX");
+ var option = AddOption(index);
+ option.SetFilter(x => x.IncludeWeeklys().Strikes(-30, 30).Expiration(0, 7));
+ }
+ }
+}
diff --git a/Algorithm.CSharp/BinanceCashAccountFeeRegressionAlgorithm.cs b/Algorithm.CSharp/BinanceCashAccountFeeRegressionAlgorithm.cs
index 6e7ae0c2c23b..1b7aad6998f8 100644
--- a/Algorithm.CSharp/BinanceCashAccountFeeRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/BinanceCashAccountFeeRegressionAlgorithm.cs
@@ -46,7 +46,7 @@ public override void Initialize()
///
/// Data Points count of the algorithm history
///
- public override int AlgorithmHistoryDataPoints => 28;
+ public override int AlgorithmHistoryDataPoints => 5;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/BinanceMarginAccountFeeRegressionAlgorithm.cs b/Algorithm.CSharp/BinanceMarginAccountFeeRegressionAlgorithm.cs
index 4c30043f2586..823b2389af92 100644
--- a/Algorithm.CSharp/BinanceMarginAccountFeeRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/BinanceMarginAccountFeeRegressionAlgorithm.cs
@@ -46,7 +46,7 @@ public override void Initialize()
///
/// Data Points count of the algorithm history
///
- public override int AlgorithmHistoryDataPoints => 28;
+ public override int AlgorithmHistoryDataPoints => 5;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/BitfinexCashAccountFeeRegressionAlgorithm.cs b/Algorithm.CSharp/BitfinexCashAccountFeeRegressionAlgorithm.cs
index f56e8e1ed08a..1d2ca5ef72a1 100644
--- a/Algorithm.CSharp/BitfinexCashAccountFeeRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/BitfinexCashAccountFeeRegressionAlgorithm.cs
@@ -45,7 +45,7 @@ public override void Initialize()
///
/// Data Points count of the algorithm history
///
- public override int AlgorithmHistoryDataPoints => 28;
+ public override int AlgorithmHistoryDataPoints => 5;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/BitfinexMarginAccountFeeRegressionAlgorithm.cs b/Algorithm.CSharp/BitfinexMarginAccountFeeRegressionAlgorithm.cs
index 7536fe642e78..c6aeca81b5e2 100644
--- a/Algorithm.CSharp/BitfinexMarginAccountFeeRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/BitfinexMarginAccountFeeRegressionAlgorithm.cs
@@ -45,7 +45,7 @@ public override void Initialize()
///
/// Data Points count of the algorithm history
///
- public override int AlgorithmHistoryDataPoints => 28;
+ public override int AlgorithmHistoryDataPoints => 5;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/BybitCryptoFuturesRegressionAlgorithm.cs b/Algorithm.CSharp/BybitCryptoFuturesRegressionAlgorithm.cs
index b77d810a5fc8..ccda05848fda 100644
--- a/Algorithm.CSharp/BybitCryptoFuturesRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/BybitCryptoFuturesRegressionAlgorithm.cs
@@ -226,7 +226,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 60;
+ public int AlgorithmHistoryDataPoints => 10;
///
/// Final status of the algorithm
@@ -244,7 +244,7 @@ public override void OnEndOfAlgorithm()
{"Compounding Annual Return", "0%"},
{"Drawdown", "0%"},
{"Expectancy", "0"},
- {"Start Equity", "100285.86"},
+ {"Start Equity", "100285.85"},
{"End Equity", "100285.26"},
{"Net Profit", "0%"},
{"Sharpe Ratio", "0"},
diff --git a/Algorithm.CSharp/BybitCryptoRegressionAlgorithm.cs b/Algorithm.CSharp/BybitCryptoRegressionAlgorithm.cs
index 09385dcd106f..c9fb4c24878e 100644
--- a/Algorithm.CSharp/BybitCryptoRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/BybitCryptoRegressionAlgorithm.cs
@@ -135,7 +135,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 60;
+ public int AlgorithmHistoryDataPoints => 10;
///
/// Final status of the algorithm
@@ -153,7 +153,7 @@ public override void OnEndOfAlgorithm()
{"Compounding Annual Return", "0%"},
{"Drawdown", "0%"},
{"Expectancy", "0"},
- {"Start Equity", "117171.12"},
+ {"Start Equity", "117170.74"},
{"End Equity", "117244.52"},
{"Net Profit", "0%"},
{"Sharpe Ratio", "0"},
diff --git a/Algorithm.CSharp/BybitCustomDataCryptoRegressionAlgorithm.cs b/Algorithm.CSharp/BybitCustomDataCryptoRegressionAlgorithm.cs
index af3e61d55f38..63303bd45752 100644
--- a/Algorithm.CSharp/BybitCustomDataCryptoRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/BybitCustomDataCryptoRegressionAlgorithm.cs
@@ -147,7 +147,7 @@ public override BaseData Reader(SubscriptionDataConfig config, string line, Date
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 60;
+ public int AlgorithmHistoryDataPoints => 10;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/CancelOpenOrdersRegressionAlgorithm.cs b/Algorithm.CSharp/CancelOpenOrdersRegressionAlgorithm.cs
index 5f87df40d595..5fd071b242c9 100644
--- a/Algorithm.CSharp/CancelOpenOrdersRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/CancelOpenOrdersRegressionAlgorithm.cs
@@ -130,7 +130,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 120;
+ public int AlgorithmHistoryDataPoints => 20;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/CoarseFineOptionUniverseChainRegressionAlgorithm.cs b/Algorithm.CSharp/CoarseFineOptionUniverseChainRegressionAlgorithm.cs
index ca659fe4512d..6a9a39a2ae11 100644
--- a/Algorithm.CSharp/CoarseFineOptionUniverseChainRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/CoarseFineOptionUniverseChainRegressionAlgorithm.cs
@@ -47,6 +47,11 @@ public override void Initialize()
_aapl = QuantConnect.Symbol.Create("AAPL", SecurityType.Equity, Market.USA);
UniverseSettings.Resolution = Resolution.Minute;
+ // Let's disable initial price seeding, the algorithm will wait until both equity
+ // and options are added an have prices to do the tests, we don't want the equity
+ // having prices before the options are added.
+ Settings.SeedInitialPrices = false;
+
SetStartDate(2014, 06, 04);
// TWX is selected the 4th and 5th and aapl after that.
// If the algo ends on the 6th, TWX subscriptions will not be removed before OnEndOfAlgorithm is called:
@@ -206,7 +211,7 @@ public override void OnEndOfAlgorithm()
{"Lowest Capacity Asset", "AOL R735QTJ8XC9X"},
{"Portfolio Turnover", "17.64%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "a8605c1f5a9c67f60f1ddc963ec45542"}
+ {"OrderListHash", "228e694280e05c8aa24246a5866b5a83"}
};
}
}
diff --git a/Algorithm.CSharp/CoarseSelectionsAutomaticSeedRegressionAlgorithm.cs b/Algorithm.CSharp/CoarseSelectionsAutomaticSeedRegressionAlgorithm.cs
new file mode 100644
index 000000000000..16a9b60a43b2
--- /dev/null
+++ b/Algorithm.CSharp/CoarseSelectionsAutomaticSeedRegressionAlgorithm.cs
@@ -0,0 +1,120 @@
+/*
+ * 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;
+using System.Collections.Generic;
+using System.Linq;
+using QuantConnect.Data.UniverseSelection;
+
+namespace QuantConnect.Algorithm.CSharp
+{
+ ///
+ /// Regression algorithm asserting that securities added via coarse selection get automatically seeded by default
+ ///
+ public class CoarseSelectionsAutomaticSeedRegressionAlgorithm : AutomaticSeedBaseRegressionAlgorithm
+ {
+ private readonly Queue> _coarseSelections = new(new[] { "AAPL", "GOOG", "AIG", "BAC", "FB", "IBM" }
+ .Select(x => QuantConnect.Symbol.Create(x, SecurityType.Equity, Market.USA))
+ .BatchBy(2));
+
+ private HashSet _addedSecurities = new();
+
+ protected override bool ShouldHaveTradeData => true;
+ // Daily resolution, only trade data is available
+ protected override bool ShouldHaveQuoteData => false;
+ protected override bool ShouldHaveOpenInterestData => false;
+
+ public override void Initialize()
+ {
+ SetStartDate(2015, 01, 01);
+ SetEndDate(2015, 03, 01);
+ SetCash(100000);
+
+ Settings.SeedInitialPrices = true;
+ UniverseSettings.Resolution = Resolution.Daily;
+
+ AddUniverse((coarse) =>
+ {
+ var selection = _coarseSelections.Dequeue();
+ _coarseSelections.Enqueue(selection);
+ return selection;
+ });
+ }
+
+ public override void OnSecuritiesChanged(SecurityChanges changes)
+ {
+ base.OnSecuritiesChanged(changes);
+
+ foreach (var addedSecurity in changes.AddedSecurities.Where(x => !x.Symbol.IsCanonical()))
+ {
+ _addedSecurities.Add(addedSecurity.Symbol);
+ }
+ }
+
+ public override void OnEndOfAlgorithm()
+ {
+ if (!_coarseSelections.SelectMany(x => x).Order().SequenceEqual(_addedSecurities.Order()))
+ {
+ throw new RegressionTestException("Not all securities were added");
+ }
+ }
+
+ ///
+ /// Data Points count of all timeslices of algorithm
+ ///
+ public override long DataPoints => 358;
+
+ ///
+ /// Data Points count of the algorithm history
+ ///
+ public override int AlgorithmHistoryDataPoints => 390;
+
+ ///
+ /// 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", "-1.066"},
+ {"Tracking Error", "0.116"},
+ {"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/CoinbaseCryptoYearMarketTradingRegressionAlgorithm.cs b/Algorithm.CSharp/CoinbaseCryptoYearMarketTradingRegressionAlgorithm.cs
index 71aff42b6187..598444164a60 100644
--- a/Algorithm.CSharp/CoinbaseCryptoYearMarketTradingRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/CoinbaseCryptoYearMarketTradingRegressionAlgorithm.cs
@@ -104,7 +104,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 43;
+ public int AlgorithmHistoryDataPoints => 11;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/Collective2PortfolioSignalExportDemonstrationAlgorithm.cs b/Algorithm.CSharp/Collective2PortfolioSignalExportDemonstrationAlgorithm.cs
index 221427ea306c..7e4a1ab222be 100644
--- a/Algorithm.CSharp/Collective2PortfolioSignalExportDemonstrationAlgorithm.cs
+++ b/Algorithm.CSharp/Collective2PortfolioSignalExportDemonstrationAlgorithm.cs
@@ -153,7 +153,7 @@ public override void OnData(Slice slice)
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 11147;
+ public int AlgorithmHistoryDataPoints => 50;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/Collective2SignalExportDemonstrationAlgorithm.cs b/Algorithm.CSharp/Collective2SignalExportDemonstrationAlgorithm.cs
index cdfff0c7ce25..3db21ab2f84c 100644
--- a/Algorithm.CSharp/Collective2SignalExportDemonstrationAlgorithm.cs
+++ b/Algorithm.CSharp/Collective2SignalExportDemonstrationAlgorithm.cs
@@ -176,7 +176,7 @@ public override void OnData(Slice slice)
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 11147;
+ public int AlgorithmHistoryDataPoints => 50;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/ComboLegLimitOrderAlgorithm.cs b/Algorithm.CSharp/ComboLegLimitOrderAlgorithm.cs
index 710ec6fe4d09..4f95178bd97b 100644
--- a/Algorithm.CSharp/ComboLegLimitOrderAlgorithm.cs
+++ b/Algorithm.CSharp/ComboLegLimitOrderAlgorithm.cs
@@ -121,10 +121,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "0"},
{"Total Fees", "$26.00"},
{"Estimated Strategy Capacity", "$58000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZERHAT67A|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "30.22%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "ab6171073cd96df46fd9d7bce62f5594"}
+ {"OrderListHash", "6168ffaa5b9f3c389f5da52e90455889"}
};
}
}
diff --git a/Algorithm.CSharp/ComboLimitOrderAlgorithm.cs b/Algorithm.CSharp/ComboLimitOrderAlgorithm.cs
index 289ab8cb4a84..2cc45e509f8b 100644
--- a/Algorithm.CSharp/ComboLimitOrderAlgorithm.cs
+++ b/Algorithm.CSharp/ComboLimitOrderAlgorithm.cs
@@ -187,10 +187,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "0"},
{"Total Fees", "$52.00"},
{"Estimated Strategy Capacity", "$5000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZERHAT67A|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "60.91%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "100742aeee45101940dc60e26fa1aa39"}
+ {"OrderListHash", "7daf3d43bef2b023ab26517085840c0e"}
};
}
}
diff --git a/Algorithm.CSharp/ComboMarketOrderAlgorithm.cs b/Algorithm.CSharp/ComboMarketOrderAlgorithm.cs
index da2353838df8..fe437576855e 100644
--- a/Algorithm.CSharp/ComboMarketOrderAlgorithm.cs
+++ b/Algorithm.CSharp/ComboMarketOrderAlgorithm.cs
@@ -93,10 +93,10 @@ public override void OnOrderEvent(OrderEvent orderEvent)
{"Treynor Ratio", "0"},
{"Total Fees", "$26.00"},
{"Estimated Strategy Capacity", "$69000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZERHAT67A|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "30.35%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "615c795b0c450cb8e4c3cba803ebb180"}
+ {"OrderListHash", "0b9f42bc22c9c7c382bc57a64c99f7e5"}
};
}
}
diff --git a/Algorithm.CSharp/ComboOrderAlgorithm.cs b/Algorithm.CSharp/ComboOrderAlgorithm.cs
index b1a0b0f45155..6afde59ed769 100644
--- a/Algorithm.CSharp/ComboOrderAlgorithm.cs
+++ b/Algorithm.CSharp/ComboOrderAlgorithm.cs
@@ -58,7 +58,7 @@ public override void Initialize()
var option = AddOption(equity.Symbol, fillForward: true);
_optionSymbol = option.Symbol;
- option.SetFilter(u => u.Strikes(-2, +2)
+ option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2)
.Expiration(0, 180));
}
diff --git a/Algorithm.CSharp/ComboOrderTicketDemoAlgorithm.cs b/Algorithm.CSharp/ComboOrderTicketDemoAlgorithm.cs
index d50f1c44d187..9403614e436c 100644
--- a/Algorithm.CSharp/ComboOrderTicketDemoAlgorithm.cs
+++ b/Algorithm.CSharp/ComboOrderTicketDemoAlgorithm.cs
@@ -47,7 +47,7 @@ public override void Initialize()
var option = AddOption(equity.Symbol, fillForward: true);
_optionSymbol = option.Symbol;
- option.SetFilter(u => u.Strikes(-2, +2)
+ option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2)
.Expiration(0, 180));
}
@@ -243,8 +243,7 @@ public override void OnOrderEvent(OrderEvent orderEvent)
}
if (orderEvent.Quantity != order.Quantity)
{
- throw new RegressionTestException($@"OrderEvent quantity should hold the current order Quantity. Got {orderEvent.Quantity
- }, expected {order.Quantity}");
+ throw new RegressionTestException($@"OrderEvent quantity should hold the current order Quantity. Got {orderEvent.Quantity}, expected {order.Quantity}");
}
if (order is ComboLegLimitOrder && orderEvent.LimitPrice == 0)
{
@@ -303,8 +302,7 @@ public override void OnEndOfAlgorithm()
{
throw new RegressionTestException(
"There were expected 6 filled market orders, 3 filled combo limit orders and 6 filled combo leg limit orders, " +
- $@"but there were {filledComboMarketOrders.Count} filled market orders, {filledComboLimitOrders.Count
- } filled combo limit orders and {filledComboLegLimitOrders.Count} filled combo leg limit orders");
+ $@"but there were {filledComboMarketOrders.Count} filled market orders, {filledComboLimitOrders.Count} filled combo limit orders and {filledComboLegLimitOrders.Count} filled combo leg limit orders");
}
if (openOrders.Count != 0 || openOrderTickets.Count != 0)
@@ -372,10 +370,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "0"},
{"Total Fees", "$26.00"},
{"Estimated Strategy Capacity", "$2000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZERHAT67A|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "58.98%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "e69460f62d4c165fe4b4a9bff1f48962"}
+ {"OrderListHash", "bec09c16bbc4d87a4e5122f29dd5a38b"}
};
}
}
diff --git a/Algorithm.CSharp/ConsolidateRegressionAlgorithm.cs b/Algorithm.CSharp/ConsolidateRegressionAlgorithm.cs
index 9f7b09a7c8eb..297c560ebada 100644
--- a/Algorithm.CSharp/ConsolidateRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/ConsolidateRegressionAlgorithm.cs
@@ -47,7 +47,7 @@ public override void Initialize()
SetEndDate(2020, 01, 20);
var SP500 = QuantConnect.Symbol.Create(Futures.Indices.SP500EMini, SecurityType.Future, Market.CME);
- var symbol = FuturesChain(SP500).First();
+ var symbol = FuturesChain(SP500).OrderBy(x => x.Symbol.ID.Date).First();
_future = AddFutureContract(symbol);
var tradableDatesCount = QuantConnect.Time.EachTradeableDayInTimeZone(_future.Exchange.Hours,
diff --git a/Algorithm.CSharp/ContinuousFutureRolloverBaseRegressionAlgorithm.cs b/Algorithm.CSharp/ContinuousFutureRolloverBaseRegressionAlgorithm.cs
index 8975109da32c..3b8134c69420 100644
--- a/Algorithm.CSharp/ContinuousFutureRolloverBaseRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/ContinuousFutureRolloverBaseRegressionAlgorithm.cs
@@ -45,17 +45,23 @@ public abstract class ContinuousFutureRolloverBaseRegressionAlgorithm : QCAlgori
protected abstract Offset ExchangeToDataTimeZoneOffset { get; }
+ protected virtual bool SeedIntialPrices { get; }
+
private DateTimeZone DataTimeZone => TimeZones.Utc;
private DateTimeZone ExchangeTimeZone => DateTimeZone.ForOffset(ExchangeToDataTimeZoneOffset);
private bool RolloverHappened => _rolloverTime != DateTime.MinValue;
+ private BaseData MappedContractSeededData;
+
public override void Initialize()
{
SetStartDate(2013, 10, 8);
SetEndDate(2013, 12, 20);
+ Settings.SeedInitialPrices = SeedIntialPrices;
+
_originalMhdbEntry = MarketHoursDatabase.GetEntry(Market.CME, Ticker, SecurityType.Future);
var exchangeHours = new SecurityExchangeHours(ExchangeTimeZone,
_originalMhdbEntry.ExchangeHours.Holidays,
@@ -115,6 +121,9 @@ public override void OnData(Slice slice)
$"Expected {expectedMappingOldSymbol} -> {expectedMappingNewSymbol} " +
$"but was {symbolChangedEvent.OldSymbol} -> {symbolChangedEvent.NewSymbol}");
}
+
+ var mappedContract = Securities[_continuousContract.Mapped];
+ MappedContractSeededData = mappedContract.GetLastData();
}
var mappedFuture = Securities[_continuousContract.Mapped];
@@ -148,7 +157,10 @@ public override void OnData(Slice slice)
}
else if (mappedFuturePrice != 0 || !RolloverHappened)
{
- if (continuousContractPrice != mappedFuturePrice)
+ var mappedFutureData = mappedFuture.GetLastData();
+ // We only do this check is default securities seeding is desabled, else the mapped contract will have historical data
+ if ((!Settings.SeedInitialPrices || !ReferenceEquals(MappedContractSeededData, mappedFutureData)) &&
+ continuousContractPrice != mappedFuturePrice)
{
var continuousContractLastData = _continuousContract.GetLastData();
throw new RegressionTestException($"[{Time}] -- Prices do not match. " +
@@ -221,7 +233,7 @@ private void ResetMarketHoursDatabase()
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 0;
+ public virtual int AlgorithmHistoryDataPoints => 0;
///
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
diff --git a/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneAheadOfDataRegressionAlgorithm.cs b/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneAheadOfDataRegressionAlgorithm.cs
index c96e620c275a..c982f8b4d0c6 100644
--- a/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneAheadOfDataRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneAheadOfDataRegressionAlgorithm.cs
@@ -34,5 +34,10 @@ public class ContinuousFutureRolloverDailyExchangeTimeZoneAheadOfDataRegressionA
/// Data Points count of all timeslices of algorithm
///
public override long DataPoints => 483;
+
+ ///
+ /// Data Points count of the algorithm history
+ ///
+ public override int AlgorithmHistoryDataPoints => 0;
}
}
diff --git a/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneAheadOfDataWithInitialSeedRegressionAlgorithm.cs b/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneAheadOfDataWithInitialSeedRegressionAlgorithm.cs
new file mode 100644
index 000000000000..2ffbe7e930c9
--- /dev/null
+++ b/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneAheadOfDataWithInitialSeedRegressionAlgorithm.cs
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ *
+*/
+
+namespace QuantConnect.Algorithm.CSharp
+{
+ ///
+ /// Base class for regression algorithms testing that when a continuous future rollover happens,
+ /// the continuous contract is updated correctly with the new contract data.
+ /// The algorithms asserts the behavior for the case when the exchange time zone is ahead of the data time zone.
+ ///
+ public class ContinuousFutureRolloverDailyExchangeTimeZoneAheadOfDataWithInitialSeedRegressionAlgorithm
+ : ContinuousFutureRolloverDailyExchangeTimeZoneAheadOfDataRegressionAlgorithm
+ {
+ protected override bool SeedIntialPrices => true;
+ ///
+ /// Data Points count of the algorithm history
+ ///
+ public override int AlgorithmHistoryDataPoints => 15;
+ }
+}
diff --git a/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneBehindOfDataWithInitialSeedRegressionAlgorithm.cs b/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneBehindOfDataWithInitialSeedRegressionAlgorithm.cs
new file mode 100644
index 000000000000..def2d23bca51
--- /dev/null
+++ b/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneBehindOfDataWithInitialSeedRegressionAlgorithm.cs
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ *
+*/
+
+namespace QuantConnect.Algorithm.CSharp
+{
+ ///
+ /// Base class for regression algorithms testing that when a continuous future rollover happens,
+ /// the continuous contract is updated correctly with the new contract data.
+ /// The algorithms asserts the behavior for the case when the exchange time zone is behind of the data time zone.
+ ///
+ public class ContinuousFutureRolloverDailyExchangeTimeZoneBehindOfDataWithInitialSeedRegressionAlgorithm
+ : ContinuousFutureRolloverDailyExchangeTimeZoneBehindOfDataRegressionAlgorithm
+ {
+ protected override bool SeedIntialPrices => true;
+
+ ///
+ /// Data Points count of the algorithm history
+ ///
+ public override int AlgorithmHistoryDataPoints => 17;
+ }
+}
diff --git a/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneSameAsDataWithIntialSeedRegressionAlgorithm.cs b/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneSameAsDataWithIntialSeedRegressionAlgorithm.cs
new file mode 100644
index 000000000000..1a5713bac8e3
--- /dev/null
+++ b/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneSameAsDataWithIntialSeedRegressionAlgorithm.cs
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ *
+*/
+
+namespace QuantConnect.Algorithm.CSharp
+{
+ ///
+ /// Base class for regression algorithms testing that when a continuous future rollover happens,
+ /// the continuous contract is updated correctly with the new contract data.
+ /// The algorithms asserts the behavior for the case when the data time zone is the same as the exchange time zone.
+ ///
+ public class ContinuousFutureRolloverDailyExchangeTimeZoneSameAsDataWithInitialSeedRegressionAlgorithm
+ : ContinuousFutureRolloverDailyExchangeTimeZoneSameAsDataRegressionAlgorithm
+
+ {
+ protected override bool SeedIntialPrices => true;
+
+ ///
+ /// Data Points count of the algorithm history
+ ///
+ public override int AlgorithmHistoryDataPoints => 17;
+ }
+}
diff --git a/Algorithm.CSharp/ContinuousFutureRolloverHourExchangeTimeZoneAheadOfDataWithInitialSeedRegressionAlgorithm.cs b/Algorithm.CSharp/ContinuousFutureRolloverHourExchangeTimeZoneAheadOfDataWithInitialSeedRegressionAlgorithm.cs
new file mode 100644
index 000000000000..9e088413d171
--- /dev/null
+++ b/Algorithm.CSharp/ContinuousFutureRolloverHourExchangeTimeZoneAheadOfDataWithInitialSeedRegressionAlgorithm.cs
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ *
+*/
+
+namespace QuantConnect.Algorithm.CSharp
+{
+ ///
+ /// Base class for regression algorithms testing that when a continuous future rollover happens,
+ /// the continuous contract is updated correctly with the new contract data.
+ /// The algorithms asserts the behavior for the case when the exchange time zone is ahead of the data time zone.
+ ///
+ public class ContinuousFutureRolloverHourExchangeTimeZoneAheadOfDataWithInitialSeedRegressionAlgorithm
+ : ContinuousFutureRolloverHourExchangeTimeZoneAheadOfDataRegressionAlgorithm
+ {
+ protected override bool SeedIntialPrices => true;
+
+ ///
+ /// Data Points count of the algorithm history
+ ///
+ public override int AlgorithmHistoryDataPoints => 65;
+ }
+}
diff --git a/Algorithm.CSharp/ContinuousFutureRolloverHourExchangeTimeZoneBehindOfDataWithInitialSeedRegressionAlgorithm.cs b/Algorithm.CSharp/ContinuousFutureRolloverHourExchangeTimeZoneBehindOfDataWithInitialSeedRegressionAlgorithm.cs
new file mode 100644
index 000000000000..9ed875f9d432
--- /dev/null
+++ b/Algorithm.CSharp/ContinuousFutureRolloverHourExchangeTimeZoneBehindOfDataWithInitialSeedRegressionAlgorithm.cs
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ *
+*/
+
+namespace QuantConnect.Algorithm.CSharp
+{
+ ///
+ /// Base class for regression algorithms testing that when a continuous future rollover happens,
+ /// the continuous contract is updated correctly with the new contract data.
+ /// The algorithms asserts the behavior for the case when the exchange time zone is behind of the data time zone.
+ ///
+ public class ContinuousFutureRolloverHourExchangeTimeZoneBehindOfDataWithInitialSeedRegressionAlgorithm
+ : ContinuousFutureRolloverHourExchangeTimeZoneBehindOfDataRegressionAlgorithm
+ {
+ protected override bool SeedIntialPrices => true;
+
+ ///
+ /// Data Points count of the algorithm history
+ ///
+ public override int AlgorithmHistoryDataPoints => 64;
+ }
+}
diff --git a/Algorithm.CSharp/ContinuousFutureRolloverHourExchangeTimeZoneSameAsDataWithInitialSeedRegressionAlgorithm.cs b/Algorithm.CSharp/ContinuousFutureRolloverHourExchangeTimeZoneSameAsDataWithInitialSeedRegressionAlgorithm.cs
new file mode 100644
index 000000000000..894d12d113f0
--- /dev/null
+++ b/Algorithm.CSharp/ContinuousFutureRolloverHourExchangeTimeZoneSameAsDataWithInitialSeedRegressionAlgorithm.cs
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ *
+*/
+
+namespace QuantConnect.Algorithm.CSharp
+{
+ ///
+ /// Base class for regression algorithms testing that when a continuous future rollover happens,
+ /// the continuous contract is updated correctly with the new contract data.
+ /// The algorithms asserts the behavior for the case when the data time zone is the same as the exchange time zone.
+ ///
+ public class ContinuousFutureRolloverHourExchangeTimeZoneSameAsDataWithInitialSeedRegressionAlgorithm
+ : ContinuousFutureRolloverHourExchangeTimeZoneSameAsDataRegressionAlgorithm
+ {
+ protected override bool SeedIntialPrices => true;
+
+ ///
+ /// Data Points count of the algorithm history
+ ///
+ public override int AlgorithmHistoryDataPoints => 64;
+ }
+}
diff --git a/Algorithm.CSharp/ContinuousFutureRolloverMinuteExchangeTimeZoneAheadOfDataWithInitialSeedRegressionAlgorithm.cs b/Algorithm.CSharp/ContinuousFutureRolloverMinuteExchangeTimeZoneAheadOfDataWithInitialSeedRegressionAlgorithm.cs
new file mode 100644
index 000000000000..6774f5fcdc9e
--- /dev/null
+++ b/Algorithm.CSharp/ContinuousFutureRolloverMinuteExchangeTimeZoneAheadOfDataWithInitialSeedRegressionAlgorithm.cs
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ *
+*/
+
+namespace QuantConnect.Algorithm.CSharp
+{
+ ///
+ /// Base class for regression algorithms testing that when a continuous future rollover happens,
+ /// the continuous contract is updated correctly with the new contract data.
+ /// The algorithms asserts the behavior for the case when the exchange time zone is ahead of the data time zone.
+ ///
+ public class ContinuousFutureRolloverMinuteExchangeTimeZoneAheadOfDataWithInitialSeedRegressionAlgorithm
+ : ContinuousFutureRolloverMinuteExchangeTimeZoneAheadOfDataRegressionAlgorithm
+ {
+ protected override bool SeedIntialPrices => true;
+
+ ///
+ /// Data Points count of the algorithm history
+ ///
+ public override int AlgorithmHistoryDataPoints => 1958;
+ }
+}
diff --git a/Algorithm.CSharp/ContinuousFutureRolloverMinuteExchangeTimeZoneBehindOfDataWithInitialSeedRegressionAlgorithm.cs b/Algorithm.CSharp/ContinuousFutureRolloverMinuteExchangeTimeZoneBehindOfDataWithInitialSeedRegressionAlgorithm.cs
new file mode 100644
index 000000000000..7531da4271dd
--- /dev/null
+++ b/Algorithm.CSharp/ContinuousFutureRolloverMinuteExchangeTimeZoneBehindOfDataWithInitialSeedRegressionAlgorithm.cs
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ *
+*/
+
+namespace QuantConnect.Algorithm.CSharp
+{
+ ///
+ /// Base class for regression algorithms testing that when a continuous future rollover happens,
+ /// the continuous contract is updated correctly with the new contract data.
+ /// The algorithms asserts the behavior for the case when the exchange time zone is behind of the data time zone.
+ ///
+ public class ContinuousFutureRolloverMinuteExchangeTimeZoneBehindOfDataWithInitialSeedRegressionAlgorithm
+ : ContinuousFutureRolloverMinuteExchangeTimeZoneBehindOfDataRegressionAlgorithm
+ {
+ protected override bool SeedIntialPrices => true;
+
+ ///
+ /// Data Points count of the algorithm history
+ ///
+ public override int AlgorithmHistoryDataPoints => 892;
+ }
+}
diff --git a/Algorithm.CSharp/ContinuousFutureRolloverMinuteExchangeTimeZoneSameAsDataWithInitialSeedRegressionAlgorithm.cs b/Algorithm.CSharp/ContinuousFutureRolloverMinuteExchangeTimeZoneSameAsDataWithInitialSeedRegressionAlgorithm.cs
new file mode 100644
index 000000000000..cc2cc354c353
--- /dev/null
+++ b/Algorithm.CSharp/ContinuousFutureRolloverMinuteExchangeTimeZoneSameAsDataWithInitialSeedRegressionAlgorithm.cs
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ *
+*/
+
+namespace QuantConnect.Algorithm.CSharp
+{
+ ///
+ /// Base class for regression algorithms testing that when a continuous future rollover happens,
+ /// the continuous contract is updated correctly with the new contract data.
+ /// The algorithms asserts the behavior for the case when the data time zone is the same as the exchange time zone.
+ ///
+ public class ContinuousFutureRolloverMinuteExchangeTimeZoneSameAsDataWithInitialSeedRegressionAlgorithm
+ : ContinuousFutureRolloverMinuteExchangeTimeZoneSameAsDataRegressionAlgorithm
+ {
+ protected override bool SeedIntialPrices => true;
+
+ ///
+ /// Data Points count of the algorithm history
+ ///
+ public override int AlgorithmHistoryDataPoints => 668;
+ }
+}
diff --git a/Algorithm.CSharp/CoveredAndProtectiveCallStrategiesAlgorithm.cs b/Algorithm.CSharp/CoveredAndProtectiveCallStrategiesAlgorithm.cs
index 25d0f8626653..d87fe16fa006 100644
--- a/Algorithm.CSharp/CoveredAndProtectiveCallStrategiesAlgorithm.cs
+++ b/Algorithm.CSharp/CoveredAndProtectiveCallStrategiesAlgorithm.cs
@@ -138,10 +138,10 @@ protected override void LiquidateStrategy()
{"Treynor Ratio", "0"},
{"Total Fees", "$4.60"},
{"Estimated Strategy Capacity", "$120000.00"},
- {"Lowest Capacity Asset", "GOOCV WBGM92QHIYO6|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV WBGM92QHN8ZQ|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "32.18%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "c0e25967c528ec4b1281f25a7735ed92"}
+ {"OrderListHash", "f8b1dfb65e4795a7929e7f3a3edd0205"}
};
}
}
diff --git a/Algorithm.CSharp/CoveredAndProtectivePutStrategiesAlgorithm.cs b/Algorithm.CSharp/CoveredAndProtectivePutStrategiesAlgorithm.cs
index 7821533a836c..9d2d3700cdc1 100644
--- a/Algorithm.CSharp/CoveredAndProtectivePutStrategiesAlgorithm.cs
+++ b/Algorithm.CSharp/CoveredAndProtectivePutStrategiesAlgorithm.cs
@@ -138,10 +138,10 @@ protected override void LiquidateStrategy()
{"Treynor Ratio", "0"},
{"Total Fees", "$4.60"},
{"Estimated Strategy Capacity", "$160000.00"},
- {"Lowest Capacity Asset", "GOOCV 30AKMEIPOSS1Y|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 30AKMEIPOX2DI|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "32.12%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "6a09be0b3b0ec11848f3b2c520234332"}
+ {"OrderListHash", "3f95cba29e9c396bc19c0d47a889dbfb"}
};
}
}
diff --git a/Algorithm.CSharp/CoveredCallComboLimitOrderAlgorithm.cs b/Algorithm.CSharp/CoveredCallComboLimitOrderAlgorithm.cs
index cc4628f61c1b..bb36e456b12a 100644
--- a/Algorithm.CSharp/CoveredCallComboLimitOrderAlgorithm.cs
+++ b/Algorithm.CSharp/CoveredCallComboLimitOrderAlgorithm.cs
@@ -43,7 +43,7 @@ public override void Initialize()
var option = AddOption(equity.Symbol);
_optionSymbol = option.Symbol;
- option.SetFilter(u => u.Strikes(-1, +1).Expiration(0, 30));
+ option.SetFilter(u => u.StandardsOnly().Strikes(-1, +1).Expiration(0, 30));
}
///
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
@@ -70,7 +70,7 @@ public override void OnData(Slice slice)
var legs = new List { Leg.Create(atmContract.Symbol, -1), Leg.Create(atmContract.Symbol.Underlying, 100) };
var comboPrice = underlyingPrice - optionPrice;
- if(comboPrice < 734m)
+ if (comboPrice < 734m)
{
// just to make sure the price makes sense
throw new RegressionTestException($"Unexpected combo price {comboPrice}");
@@ -147,10 +147,10 @@ public override void OnOrderEvent(OrderEvent orderEvent)
{"Treynor Ratio", "0"},
{"Total Fees", "$6.90"},
{"Estimated Strategy Capacity", "$8000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZFMEBBB2E|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZFMEBFLDY|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "227.27%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "94a9ae926f68c23d06d32af2b5a25fea"}
+ {"OrderListHash", "e36c11e174486d80060855efed57a2a9"}
};
}
}
diff --git a/Algorithm.CSharp/CustomDataAutomaticSeedRegressionAlgorithm.cs b/Algorithm.CSharp/CustomDataAutomaticSeedRegressionAlgorithm.cs
new file mode 100644
index 000000000000..11751eaade2d
--- /dev/null
+++ b/Algorithm.CSharp/CustomDataAutomaticSeedRegressionAlgorithm.cs
@@ -0,0 +1,232 @@
+/*
+ * 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;
+using System.Collections.Generic;
+using System.Globalization;
+using Newtonsoft.Json;
+using QuantConnect.Data;
+using QuantConnect.Interfaces;
+
+namespace QuantConnect.Algorithm.CSharp
+{
+ ///
+ /// Regression test to assert that custom data is seeded by default
+ ///
+ public class CustomDataAutomaticSeedRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
+ {
+ public override void Initialize()
+ {
+ SetStartDate(2020, 01, 05);
+ SetEndDate(2020, 01, 10);
+ SetCash(100000);
+
+ Settings.SeedInitialPrices = true;
+
+ var resolution = Resolution.Daily;
+ var customData = AddData("BTC", resolution);
+
+ if (!customData.HasData || customData.Price == 0)
+ {
+ throw new RegressionTestException("Custom data was not seeded with data on addition");
+ }
+
+ var seedData = customData.GetLastData();
+ if (seedData is not Bitcoin)
+ {
+ throw new RegressionTestException("Custom data was not seeded with correct data type");
+ }
+ }
+
+ ///
+ /// 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 => 50;
+
+ ///
+ /// Data Points count of the algorithm history
+ ///
+ public int AlgorithmHistoryDataPoints => 5;
+
+ ///
+ /// 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", "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", "-9.259"},
+ {"Tracking Error", "0.073"},
+ {"Treynor Ratio", "0"},
+ {"Total Fees", "$0.00"},
+ {"Estimated Strategy Capacity", "$0"},
+ {"Lowest Capacity Asset", ""},
+ {"Portfolio Turnover", "0%"},
+ {"Drawdown Recovery", "0"},
+ {"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
+ };
+
+ ///
+ /// Custom Data Type: Bitcoin data from Quandl - http://www.quandl.com/help/api-for-bitcoin-data
+ ///
+ public class Bitcoin : BaseData
+ {
+ [JsonProperty("timestamp")]
+ public int Timestamp { get; set; }
+ [JsonProperty("open")]
+ public decimal Open { get; set; }
+ [JsonProperty("high")]
+ public decimal High { get; set; }
+ [JsonProperty("low")]
+ public decimal Low { get; set; }
+ public decimal Mid { get; set; }
+
+ [JsonProperty("last")]
+ public decimal Close { get; set; }
+ [JsonProperty("bid")]
+ public decimal Bid { get; set; }
+ [JsonProperty("ask")]
+ public decimal Ask { get; set; }
+ [JsonProperty("vwap")]
+ public decimal WeightedPrice { get; set; }
+ [JsonProperty("volume")]
+ public decimal VolumeBTC { get; set; }
+
+ ///
+ /// The end time of this data. Some data covers spans (trade bars)
+ /// and as such we want to know the entire time span covered
+ ///
+ ///
+ /// This property is overriden to allow different values for Time and EndTime
+ /// if they are set in the Reader. In the base implementation EndTime equals Time
+ ///
+ public override DateTime EndTime { get; set; }
+
+ ///
+ /// 1. DEFAULT CONSTRUCTOR: Custom data types need a default constructor.
+ /// We search for a default constructor so please provide one here. It won't be used for data, just to generate the "Factory".
+ ///
+ public Bitcoin()
+ {
+ Symbol = "BTC";
+ }
+
+ ///
+ /// 2. RETURN THE STRING URL SOURCE LOCATION FOR YOUR DATA:
+ /// This is a powerful and dynamic select source file method. If you have a large dataset, 10+mb we recommend you break it into smaller files. E.g. One zip per year.
+ /// We can accept raw text or ZIP files. We read the file extension to determine if it is a zip file.
+ ///
+ /// Configuration object
+ /// Date of this source file
+ /// true if we're in live mode, false for backtesting mode
+ /// String URL of source file.
+ public override SubscriptionDataSource GetSource(SubscriptionDataConfig config, DateTime date, bool isLiveMode)
+ {
+ if (isLiveMode)
+ {
+ return new SubscriptionDataSource("https://www.bitstamp.net/api/ticker/", SubscriptionTransportMedium.Rest);
+ }
+
+ //return "http://my-ftp-server.com/futures-data-" + date.ToString("Ymd") + ".zip";
+ // OR simply return a fixed small data file. Large files will slow down your backtest
+ return new SubscriptionDataSource("https://www.quantconnect.com/api/v2/proxy/nasdaq/api/v3/datatables/QDL/BITFINEX.csv?code=BTCUSD&api_key=qAWKpUfmSVFnU3bRQwKy")
+ {
+ Sort = true
+ };
+ }
+
+ ///
+ /// 3. READER METHOD: Read 1 line from data source and convert it into Object.
+ /// Each line of the CSV File is presented in here. The backend downloads your file, loads it into memory and then line by line
+ /// feeds it into your algorithm
+ ///
+ /// string line from the data source file submitted above
+ /// Subscription data, symbol name, data type
+ /// Current date we're requesting. This allows you to break up the data source into daily files.
+ /// true if we're in live mode, false for backtesting mode
+ /// New Bitcoin Object which extends BaseData.
+ public override BaseData Reader(SubscriptionDataConfig config, string line, DateTime date, bool isLiveMode)
+ {
+ var coin = new Bitcoin();
+ if (isLiveMode)
+ {
+ //Example Line Format:
+ //{"high": "441.00", "last": "421.86", "timestamp": "1411606877", "bid": "421.96", "vwap": "428.58", "volume": "14120.40683975", "low": "418.83", "ask": "421.99"}
+ try
+ {
+ coin = JsonConvert.DeserializeObject(line);
+ coin.EndTime = DateTime.UtcNow.ConvertFromUtc(config.ExchangeTimeZone);
+ coin.Value = coin.Close;
+ }
+ catch { /* Do nothing, possible error in json decoding */ }
+ return coin;
+ }
+
+ //Example Line Format:
+ // code date high low mid last bid ask volume
+ // BTCUSD 2024-10-08 63248.0 61940.0 62246.5 62245.0 62246.0 62247.0 477.91102114
+ try
+ {
+ string[] data = line.Split(',');
+ coin.Time = DateTime.Parse(data[1], CultureInfo.InvariantCulture);
+ coin.EndTime = coin.Time.AddDays(1);
+ coin.High = Convert.ToDecimal(data[2], CultureInfo.InvariantCulture);
+ coin.Low = Convert.ToDecimal(data[3], CultureInfo.InvariantCulture);
+ coin.Mid = Convert.ToDecimal(data[4], CultureInfo.InvariantCulture);
+ coin.Close = Convert.ToDecimal(data[5], CultureInfo.InvariantCulture);
+ coin.Bid = Convert.ToDecimal(data[6], CultureInfo.InvariantCulture);
+ coin.Ask = Convert.ToDecimal(data[7], CultureInfo.InvariantCulture);
+ coin.VolumeBTC = Convert.ToDecimal(data[8], CultureInfo.InvariantCulture);
+ coin.Value = coin.Close;
+ }
+ catch { /* Do nothing, skip first title row */ }
+
+ return coin;
+ }
+ }
+ }
+}
diff --git a/Algorithm.CSharp/CustomDataPropertiesRegressionAlgorithm.cs b/Algorithm.CSharp/CustomDataPropertiesRegressionAlgorithm.cs
index 1534c82ea0dc..fba19955843a 100644
--- a/Algorithm.CSharp/CustomDataPropertiesRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/CustomDataPropertiesRegressionAlgorithm.cs
@@ -198,7 +198,6 @@ public class Bitcoin : BaseData
///
public Bitcoin()
{
- Symbol = "BTC";
}
///
@@ -237,7 +236,7 @@ public override SubscriptionDataSource GetSource(SubscriptionDataConfig config,
/// New Bitcoin Object which extends BaseData.
public override BaseData Reader(SubscriptionDataConfig config, string line, DateTime date, bool isLiveMode)
{
- var coin = new Bitcoin();
+ var coin = new Bitcoin() { Symbol = config.Symbol };
if (isLiveMode)
{
//Example Line Format:
diff --git a/Algorithm.CSharp/CustomDataWorksWithDifferentExchangesRegressionAlgorithm.cs b/Algorithm.CSharp/CustomDataWorksWithDifferentExchangesRegressionAlgorithm.cs
index 71cf23798821..fc7a4360f09e 100644
--- a/Algorithm.CSharp/CustomDataWorksWithDifferentExchangesRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/CustomDataWorksWithDifferentExchangesRegressionAlgorithm.cs
@@ -83,7 +83,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 60;
+ public int AlgorithmHistoryDataPoints => 5;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/CustomOptionAssignmentRegressionAlgorithm.cs b/Algorithm.CSharp/CustomOptionAssignmentRegressionAlgorithm.cs
index e53cc9836cc6..2c2c8c2360b8 100644
--- a/Algorithm.CSharp/CustomOptionAssignmentRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/CustomOptionAssignmentRegressionAlgorithm.cs
@@ -83,10 +83,10 @@ public override OptionAssignmentResult GetAssignment(OptionAssignmentParameters
{"Treynor Ratio", "-0.115"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$4800000.00"},
- {"Lowest Capacity Asset", "GOOCV 305RBQ20WHPNQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 305RBQ20WLZZA|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "26.72%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "fb2bef182af109f6441ae739d826f39f"}
+ {"OrderListHash", "20f33e143b62ee896aa56f85dd2aa2e8"}
};
}
}
diff --git a/Algorithm.CSharp/CustomOptionExerciseModelRegressionAlgorithm.cs b/Algorithm.CSharp/CustomOptionExerciseModelRegressionAlgorithm.cs
index c1df92e98d8f..cb57aea29042 100644
--- a/Algorithm.CSharp/CustomOptionExerciseModelRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/CustomOptionExerciseModelRegressionAlgorithm.cs
@@ -91,10 +91,10 @@ public override IEnumerable OptionExercise(Option option, OptionExer
{"Treynor Ratio", "-3.295"},
{"Total Fees", "$16.00"},
{"Estimated Strategy Capacity", "$87000.00"},
- {"Lowest Capacity Asset", "GOOCV 305RBQ20WHPNQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 305RBQ20WLZZA|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "10.93%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "8133cb99a1a9f9e9335bc98def3cc624"}
+ {"OrderListHash", "19b8f2a8081c3cfa8f6bc02b5d045765"}
};
}
}
diff --git a/Algorithm.CSharp/CustomSecurityInitializerAlgorithm.cs b/Algorithm.CSharp/CustomSecurityInitializerAlgorithm.cs
index e30e808caf64..ae4ba351d154 100644
--- a/Algorithm.CSharp/CustomSecurityInitializerAlgorithm.cs
+++ b/Algorithm.CSharp/CustomSecurityInitializerAlgorithm.cs
@@ -1,4 +1,4 @@
-/*
+/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
diff --git a/Algorithm.CSharp/DailyHistoryForDailyResolutionRegressionAlgorithm.cs b/Algorithm.CSharp/DailyHistoryForDailyResolutionRegressionAlgorithm.cs
index 93479ffcf571..093d906eda8f 100644
--- a/Algorithm.CSharp/DailyHistoryForDailyResolutionRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/DailyHistoryForDailyResolutionRegressionAlgorithm.cs
@@ -101,7 +101,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 564;
+ public int AlgorithmHistoryDataPoints => 458;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/DailyHistoryForMinuteResolutionRegressionAlgorithm.cs b/Algorithm.CSharp/DailyHistoryForMinuteResolutionRegressionAlgorithm.cs
index 5394ffa04328..35c4e458624c 100644
--- a/Algorithm.CSharp/DailyHistoryForMinuteResolutionRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/DailyHistoryForMinuteResolutionRegressionAlgorithm.cs
@@ -103,7 +103,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 43089;
+ public int AlgorithmHistoryDataPoints => 15307;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/DailyOptionChainOpenInterestDataWithStrictDailyEndTimesRegressionAlgorithm.cs b/Algorithm.CSharp/DailyOptionChainOpenInterestDataWithStrictDailyEndTimesRegressionAlgorithm.cs
index 575f79648c14..999fb1e70620 100644
--- a/Algorithm.CSharp/DailyOptionChainOpenInterestDataWithStrictDailyEndTimesRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/DailyOptionChainOpenInterestDataWithStrictDailyEndTimesRegressionAlgorithm.cs
@@ -40,7 +40,7 @@ public override void Initialize()
SetEndDate(2014, 07, 06);
var option = AddOption("AAPL", Resolution.Daily);
- option.SetFilter(-5, +5, 0, 365);
+ option.SetFilter(u => u.StandardsOnly().Strikes(-5, +5).Expiration(0, 365));
_symbol = option.Symbol;
}
@@ -81,7 +81,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public virtual long DataPoints => 47132;
+ public virtual long DataPoints => 47140;
///
/// Data Points count of the algorithm history
@@ -117,7 +117,7 @@ public override void OnEndOfAlgorithm()
{"Beta", "0"},
{"Annual Standard Deviation", "0"},
{"Annual Variance", "0"},
- {"Information Ratio", "-5.732"},
+ {"Information Ratio", "-6.035"},
{"Tracking Error", "0.05"},
{"Treynor Ratio", "0"},
{"Total Fees", "$0.00"},
diff --git a/Algorithm.CSharp/DailyOptionChainOpenInterestDataWithoutStrictDailyEndTimesRegressionAlgorithm.cs b/Algorithm.CSharp/DailyOptionChainOpenInterestDataWithoutStrictDailyEndTimesRegressionAlgorithm.cs
index ff07abc720c4..74b04bd5cd77 100644
--- a/Algorithm.CSharp/DailyOptionChainOpenInterestDataWithoutStrictDailyEndTimesRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/DailyOptionChainOpenInterestDataWithoutStrictDailyEndTimesRegressionAlgorithm.cs
@@ -26,6 +26,6 @@ public class DailyOptionChainOpenInterestDataWithoutStrictDailyEndTimesRegressio
///
/// Data Points count of all timeslices of algorithm
///
- public override long DataPoints => 46264;
+ public override long DataPoints => 46271;
}
}
diff --git a/Algorithm.CSharp/DailyResolutionVsTimeSpanRegressionAlgorithm.cs b/Algorithm.CSharp/DailyResolutionVsTimeSpanRegressionAlgorithm.cs
index a937d9ba2150..eeba2f06f68a 100644
--- a/Algorithm.CSharp/DailyResolutionVsTimeSpanRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/DailyResolutionVsTimeSpanRegressionAlgorithm.cs
@@ -38,7 +38,7 @@ public override void Initialize()
Settings.DailyPreciseEndTime = DailyPreciseEndTime;
- // First RSI: Updates at market close (4 PM) by default
+ // First RSI: Updates at market close (4 PM) by default
// If DailyPreciseEndTime is false, updates at midnight (12:00 AM)
RelativeStrengthIndex1 = new RelativeStrengthIndex(14, MovingAverageType.Wilders);
RegisterIndicator(Spy, RelativeStrengthIndex1, Resolution.Daily);
diff --git a/Algorithm.CSharp/DailyResolutionVsTimeSpanWithSecondEquityAlgorithm.cs b/Algorithm.CSharp/DailyResolutionVsTimeSpanWithSecondEquityAlgorithm.cs
index d4431df85d44..a5b6bbc19eae 100644
--- a/Algorithm.CSharp/DailyResolutionVsTimeSpanWithSecondEquityAlgorithm.cs
+++ b/Algorithm.CSharp/DailyResolutionVsTimeSpanWithSecondEquityAlgorithm.cs
@@ -17,7 +17,7 @@
namespace QuantConnect.Algorithm.CSharp
{
- public class DailyResolutionVsTimeSpanWithSecondResolutionEquityAlgorithm : DailyResolutionVsTimeSpanRegressionAlgorithm
+ public class DailyResolutionVsTimeSpanWithSecondEquityAlgorithm : DailyResolutionVsTimeSpanRegressionAlgorithm
{
protected override void InitializeBaseSettings()
{
@@ -62,7 +62,8 @@ protected override void InitializeBaseSettings()
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", ""},
{"Portfolio Turnover", "0%"},
+ {"Drawdown Recovery", "0"},
{"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
};
}
-}
\ No newline at end of file
+}
diff --git a/Algorithm.CSharp/DefaultFutureChainRegressionAlgorithm.cs b/Algorithm.CSharp/DefaultFutureChainRegressionAlgorithm.cs
index 05de0d98977d..9ac3347d43d9 100644
--- a/Algorithm.CSharp/DefaultFutureChainRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/DefaultFutureChainRegressionAlgorithm.cs
@@ -62,7 +62,7 @@ public override void OnSecuritiesChanged(SecurityChanges changes)
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 70735;
+ public long DataPoints => 70736;
///
/// Data Points count of the algorithm history
diff --git a/Algorithm.CSharp/DefaultMarginComboOrderRegressionAlgorithm.cs b/Algorithm.CSharp/DefaultMarginComboOrderRegressionAlgorithm.cs
index 794a1afd7551..e776b7f00fb5 100644
--- a/Algorithm.CSharp/DefaultMarginComboOrderRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/DefaultMarginComboOrderRegressionAlgorithm.cs
@@ -82,7 +82,7 @@ protected override void AssertState(OrderTicket ticket, int expectedGroupCount,
{"Lowest Capacity Asset", ""},
{"Portfolio Turnover", "0%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "2d5054cdc5dd7701845823749255ce1c"}
+ {"OrderListHash", "73b6f756bf1eacbe11b72be54bc13103"}
};
}
}
diff --git a/Algorithm.CSharp/DefaultMarginMultipleOrdersRegressionAlgorithm.cs b/Algorithm.CSharp/DefaultMarginMultipleOrdersRegressionAlgorithm.cs
index 90e1257b675d..c457a2fe4a29 100644
--- a/Algorithm.CSharp/DefaultMarginMultipleOrdersRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/DefaultMarginMultipleOrdersRegressionAlgorithm.cs
@@ -82,7 +82,7 @@ protected override void AssertState(OrderTicket ticket, int expectedGroupCount,
{"Lowest Capacity Asset", ""},
{"Portfolio Turnover", "0%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "d9133c55f97224d3fd291607d75a6aeb"}
+ {"OrderListHash", "f5636192a24570f4a1a95ee49e4073a8"}
};
}
}
diff --git a/Algorithm.CSharp/DelayedSettlementAfterManualSecurityRemovalAlgorithm.cs b/Algorithm.CSharp/DelayedSettlementAfterManualSecurityRemovalAlgorithm.cs
index e26d5fa9794f..43c24c4e1c93 100644
--- a/Algorithm.CSharp/DelayedSettlementAfterManualSecurityRemovalAlgorithm.cs
+++ b/Algorithm.CSharp/DelayedSettlementAfterManualSecurityRemovalAlgorithm.cs
@@ -105,7 +105,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 7122;
+ public long DataPoints => 7123;
///
/// Data Points count of the algorithm history
@@ -146,10 +146,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "0"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$720000.00"},
- {"Lowest Capacity Asset", "GOOCV WHEA9CWI9A86|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV WHEA9CWIDKJQ|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "11.63%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "65ac4f8e4de760fec3809bf1aa3e0e9c"}
+ {"OrderListHash", "d0d7b2b1f483d16e72863ecf3bbc3ed6"}
};
}
}
diff --git a/Algorithm.CSharp/DelistedFutureLiquidateFromChainAndContinuousMidnightExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/DelistedFutureLiquidateFromChainAndContinuousMidnightExpiryRegressionAlgorithm.cs
new file mode 100644
index 000000000000..cb08750a51df
--- /dev/null
+++ b/Algorithm.CSharp/DelistedFutureLiquidateFromChainAndContinuousMidnightExpiryRegressionAlgorithm.cs
@@ -0,0 +1,76 @@
+/*
+ * 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.Securities;
+
+namespace QuantConnect.Algorithm.CSharp
+{
+ ///
+ /// Regression algorithm asserting that a future contract selected by both the continuous future and
+ /// the future chain universes gets liquidated on delisting and that the algorithm receives the correct
+ /// security addition/removal notifications.
+ ///
+ /// This algorithm uses Gold futures with midnight expiry time to reproduce an edge case where
+ /// the delisting data instance and the universe deselection happen in the same loop but without a particular order.
+ ///
+ /// This partly reproduces GH issue https://github.com/QuantConnect/Lean/issues/9092
+ ///
+ public class DelistedFutureLiquidateFromChainAndContinuousMidnightExpiryRegressionAlgorithm : DelistedFutureLiquidateFromChainAndContinuousRegressionAlgorithm
+ {
+ protected override string FutureTicker => Futures.Metals.Gold;
+
+ ///
+ /// Data Points count of all timeslices of algorithm
+ ///
+ public override long DataPoints => 317492;
+
+ ///
+ /// 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", "2"},
+ {"Average Win", "0%"},
+ {"Average Loss", "-5.18%"},
+ {"Compounding Annual Return", "-20.700%"},
+ {"Drawdown", "6.400%"},
+ {"Expectancy", "-1"},
+ {"Start Equity", "100000"},
+ {"End Equity", "94817.53"},
+ {"Net Profit", "-5.182%"},
+ {"Sharpe Ratio", "-2.965"},
+ {"Sortino Ratio", "-3.407"},
+ {"Probabilistic Sharpe Ratio", "0.000%"},
+ {"Loss Rate", "100%"},
+ {"Win Rate", "0%"},
+ {"Profit-Loss Ratio", "0"},
+ {"Alpha", "-0.064"},
+ {"Beta", "-0.2"},
+ {"Annual Standard Deviation", "0.048"},
+ {"Annual Variance", "0.002"},
+ {"Information Ratio", "-4.899"},
+ {"Tracking Error", "0.11"},
+ {"Treynor Ratio", "0.716"},
+ {"Total Fees", "$2.47"},
+ {"Estimated Strategy Capacity", "$1400000.00"},
+ {"Lowest Capacity Asset", "GC VL5E74HP3EE5"},
+ {"Portfolio Turnover", "3.18%"},
+ {"Drawdown Recovery", "0"},
+ {"OrderListHash", "c197fe000cd6d7f2fd84860f7086d730"}
+ };
+ }
+}
diff --git a/Algorithm.CSharp/DelistedFutureLiquidateFromChainAndContinuousRegressionAlgorithm.cs b/Algorithm.CSharp/DelistedFutureLiquidateFromChainAndContinuousRegressionAlgorithm.cs
new file mode 100644
index 000000000000..873f7a015838
--- /dev/null
+++ b/Algorithm.CSharp/DelistedFutureLiquidateFromChainAndContinuousRegressionAlgorithm.cs
@@ -0,0 +1,196 @@
+/*
+ * 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;
+using System.Collections.Generic;
+using System.Linq;
+using QuantConnect.Data;
+using QuantConnect.Data.UniverseSelection;
+using QuantConnect.Interfaces;
+using QuantConnect.Orders;
+using QuantConnect.Securities;
+using QuantConnect.Securities.Future;
+
+namespace QuantConnect.Algorithm.CSharp
+{
+ ///
+ /// Regression algorithm asserting that a future contract selected by both the continuous future and
+ /// the future chain universes gets liquidated on delisting and that the algorithm receives the correct
+ /// security addition/removal notifications.
+ ///
+ /// This partly reproduces GH issue https://github.com/QuantConnect/Lean/issues/9092
+ ///
+ public class DelistedFutureLiquidateFromChainAndContinuousRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
+ {
+ private Symbol _contractSymbol;
+
+ private Future _continuousFuture;
+
+ private DateTime _internalContractRemovalTime;
+ private DateTime _contractRemovalTime;
+
+ protected virtual string FutureTicker => Futures.Indices.SP500EMini;
+
+ public override void Initialize()
+ {
+ SetStartDate(2013, 10, 08);
+ SetEndDate(2013, 12, 30);
+
+ _continuousFuture = AddFuture(FutureTicker);
+ _continuousFuture.SetFilter(0, 182);
+ }
+
+ public override void OnData(Slice slice)
+ {
+ if (_contractSymbol == null)
+ {
+ foreach (var chain in slice.FutureChains)
+ {
+ // Make sure the mapped contract is in the chain, that is, is selected by both universes
+ if (chain.Value.Any(x => x.Symbol == _continuousFuture.Mapped))
+ {
+ _contractSymbol = _continuousFuture.Mapped;
+ var ticket = MarketOrder(_contractSymbol, 1);
+
+ if (ticket.Status != OrderStatus.Filled)
+ {
+ throw new RegressionTestException($"Order should be filled: {ticket}");
+ }
+ }
+ }
+ }
+ }
+
+ public override void OnSecuritiesChanged(SecurityChanges changes)
+ {
+ if (changes.RemovedSecurities.Any(x => x.Symbol == _contractSymbol))
+ {
+ if (_contractRemovalTime != default)
+ {
+ throw new RegressionTestException($"Contract {_contractSymbol} was removed multiple times");
+ }
+ _contractRemovalTime = Time;
+ }
+ else
+ {
+ changes.FilterInternalSecurities = false;
+ if (changes.RemovedSecurities.Any(x => x.Symbol == _contractSymbol))
+ {
+ if (_internalContractRemovalTime != default)
+ {
+ throw new RegressionTestException($"Contract {_contractSymbol} was removed multiple times as internal subscription");
+ }
+ _internalContractRemovalTime = Time;
+ }
+ }
+ }
+
+ public override void OnEndOfAlgorithm()
+ {
+ if (_contractSymbol == null)
+ {
+ throw new RegressionTestException("No contract was ever traded");
+ }
+
+ if (_internalContractRemovalTime == default)
+ {
+ throw new RegressionTestException($"Contract {_contractSymbol} was not removed from the algorithm");
+ }
+
+ if (_contractRemovalTime == default)
+ {
+ throw new RegressionTestException($"Contract {_contractSymbol} was not removed from the algorithm as external subscription");
+ }
+
+ // The internal subscription should be removed first (on continuous future mapping),
+ // and the regular subscription later (on delisting)
+ if (_contractRemovalTime < _internalContractRemovalTime)
+ {
+ throw new RegressionTestException($"Contract {_contractSymbol} was removed from the algorithm as aregular subscription before internal subscription");
+ }
+
+ if (Securities[_contractSymbol].Invested)
+ {
+ throw new RegressionTestException($"Position should be closed when {_contractSymbol} got delisted {_contractSymbol.ID.Date}");
+ }
+ }
+
+ public override void OnOrderEvent(OrderEvent orderEvent)
+ {
+ Log($"{orderEvent}. Delisting on: {_contractSymbol.ID.Date}");
+ }
+
+ ///
+ /// 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 virtual long DataPoints => 288140;
+
+ ///
+ /// 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 virtual Dictionary ExpectedStatistics => new Dictionary
+ {
+ {"Total Orders", "2"},
+ {"Average Win", "7.02%"},
+ {"Average Loss", "0%"},
+ {"Compounding Annual Return", "34.386%"},
+ {"Drawdown", "1.500%"},
+ {"Expectancy", "0"},
+ {"Start Equity", "100000"},
+ {"End Equity", "107016.6"},
+ {"Net Profit", "7.017%"},
+ {"Sharpe Ratio", "3.217"},
+ {"Sortino Ratio", "0"},
+ {"Probabilistic Sharpe Ratio", "99.828%"},
+ {"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"},
+ {"Total Fees", "$2.15"},
+ {"Estimated Strategy Capacity", "$1700000000.00"},
+ {"Lowest Capacity Asset", "ES VMKLFZIH2MTD"},
+ {"Portfolio Turnover", "2.01%"},
+ {"Drawdown Recovery", "16"},
+ {"OrderListHash", "640ce720644ff0b580687e80105d0a92"}
+ };
+ }
+}
diff --git a/Algorithm.CSharp/DelistedFutureLiquidateRegressionAlgorithm.cs b/Algorithm.CSharp/DelistedFutureLiquidateRegressionAlgorithm.cs
index e5c1fe8c119f..f1294c24de1f 100644
--- a/Algorithm.CSharp/DelistedFutureLiquidateRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/DelistedFutureLiquidateRegressionAlgorithm.cs
@@ -18,6 +18,7 @@
using System.Collections.Generic;
using System.Linq;
using QuantConnect.Data;
+using QuantConnect.Data.UniverseSelection;
using QuantConnect.Interfaces;
using QuantConnect.Orders;
using QuantConnect.Securities;
@@ -30,6 +31,7 @@ namespace QuantConnect.Algorithm.CSharp
public class DelistedFutureLiquidateRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Symbol _contractSymbol;
+ private bool _contractRemoved;
protected virtual Resolution Resolution => Resolution.Minute;
///
@@ -65,8 +67,21 @@ public override void OnData(Slice slice)
}
}
+ public override void OnSecuritiesChanged(SecurityChanges changes)
+ {
+ if (changes.RemovedSecurities.Any(x => x.Symbol == _contractSymbol))
+ {
+ _contractRemoved = true;
+ }
+ }
+
public override void OnEndOfAlgorithm()
{
+ if (!_contractRemoved)
+ {
+ throw new RegressionTestException($"Contract {_contractSymbol} was not removed from the algorithm");
+ }
+
Log($"{_contractSymbol}: {Securities[_contractSymbol].Invested}");
if (Securities[_contractSymbol].Invested)
{
diff --git a/Algorithm.CSharp/DelistedIndexOptionDivestedRegression.cs b/Algorithm.CSharp/DelistedIndexOptionDivestedRegression.cs
index 67f8274cad0a..2e9c1ccf8c4a 100644
--- a/Algorithm.CSharp/DelistedIndexOptionDivestedRegression.cs
+++ b/Algorithm.CSharp/DelistedIndexOptionDivestedRegression.cs
@@ -120,7 +120,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 17099;
+ public long DataPoints => 17100;
///
/// Data Points count of the algorithm history
@@ -161,10 +161,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "1.124"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$1000000.00"},
- {"Lowest Capacity Asset", "SPX 31KC0UJFONTBI|SPX 31"},
+ {"Lowest Capacity Asset", "SPX 31KC0UJFOS3N2|SPX 31"},
{"Portfolio Turnover", "1.24%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "4d70dc21785d91df8755e1499f3f68e1"}
+ {"OrderListHash", "eea2a6b8ea827058d695cd5a7bb338ab"}
};
}
}
diff --git a/Algorithm.CSharp/DelistingEventsAlgorithm.cs b/Algorithm.CSharp/DelistingEventsAlgorithm.cs
index a6da34f2c290..5cd03a378246 100644
--- a/Algorithm.CSharp/DelistingEventsAlgorithm.cs
+++ b/Algorithm.CSharp/DelistingEventsAlgorithm.cs
@@ -153,7 +153,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 86;
+ public long DataPoints => 87;
///
/// Data Points count of the algorithm history
diff --git a/Algorithm.CSharp/DelistingFutureOptionDailyRegressionAlgorithm.cs b/Algorithm.CSharp/DelistingFutureOptionDailyRegressionAlgorithm.cs
index 30d53f928fef..e64888704c58 100644
--- a/Algorithm.CSharp/DelistingFutureOptionDailyRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/DelistingFutureOptionDailyRegressionAlgorithm.cs
@@ -59,10 +59,10 @@ public class DelistingFutureOptionDailyRegressionAlgorithm : DelistingFutureOpti
{"Treynor Ratio", "-84.756"},
{"Total Fees", "$1.42"},
{"Estimated Strategy Capacity", "$540000000.00"},
- {"Lowest Capacity Asset", "ES XCZJLDREXSX0|ES XCZJLC9NOB29"},
+ {"Lowest Capacity Asset", "ES XCZJLDRF238K|ES XCZJLC9NOB29"},
{"Portfolio Turnover", "0.04%"},
{"Drawdown Recovery", "3"},
- {"OrderListHash", "f8c078f0d4552a15538508966a440c5a"}
+ {"OrderListHash", "11ac76bc66928a5e97e064281f6e7ef5"}
};
}
}
diff --git a/Algorithm.CSharp/DelistingFutureOptionRegressionAlgorithm.cs b/Algorithm.CSharp/DelistingFutureOptionRegressionAlgorithm.cs
index 905a66fd4763..79fcc59031c8 100644
--- a/Algorithm.CSharp/DelistingFutureOptionRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/DelistingFutureOptionRegressionAlgorithm.cs
@@ -146,10 +146,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "-15.266"},
{"Total Fees", "$11.36"},
{"Estimated Strategy Capacity", "$65000000.00"},
- {"Lowest Capacity Asset", "ES XCZJLDQX2SRO|ES XCZJLC9NOB29"},
+ {"Lowest Capacity Asset", "ES XCZJLDQR8R1G|ES XCZJLC9NOB29"},
{"Portfolio Turnover", "0.16%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "224292a1aace8a0895ea272d84714eac"}
+ {"OrderListHash", "f9210adc1afc4460146528006675e734"}
};
}
}
diff --git a/Algorithm.CSharp/DuplicateOptionAssignmentRegressionAlgorithm.cs b/Algorithm.CSharp/DuplicateOptionAssignmentRegressionAlgorithm.cs
index 30368ac2610b..0e412d41a747 100644
--- a/Algorithm.CSharp/DuplicateOptionAssignmentRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/DuplicateOptionAssignmentRegressionAlgorithm.cs
@@ -213,7 +213,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 2849;
+ public long DataPoints => 2850;
///
/// Data Points count of the algorithm history
@@ -254,10 +254,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "1.883"},
{"Total Fees", "$1.00"},
{"Estimated Strategy Capacity", "$1300000.00"},
- {"Lowest Capacity Asset", "GOOCV 305RBQ20WHPNQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 305RBQ20WLZZA|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "7.07%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "fff8641650865d3ac20351d33ac9b204"}
+ {"OrderListHash", "79ecc4dd8b045ddf0aa38057b8eb69bf"}
};
}
}
diff --git a/Algorithm.CSharp/EmitInsightCryptoCashAccountType.cs b/Algorithm.CSharp/EmitInsightCryptoCashAccountType.cs
index 6ea12e46f3e1..528bfc773784 100644
--- a/Algorithm.CSharp/EmitInsightCryptoCashAccountType.cs
+++ b/Algorithm.CSharp/EmitInsightCryptoCashAccountType.cs
@@ -74,7 +74,7 @@ public override void OnData(Slice slice)
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 120;
+ public int AlgorithmHistoryDataPoints => 15;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/EquityTickQuoteAdjustedModeRegressionAlgorithm.cs b/Algorithm.CSharp/EquityTickQuoteAdjustedModeRegressionAlgorithm.cs
index 07060346811c..0d7c0dfc6e59 100644
--- a/Algorithm.CSharp/EquityTickQuoteAdjustedModeRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/EquityTickQuoteAdjustedModeRegressionAlgorithm.cs
@@ -125,7 +125,7 @@ public override void OnData(Slice slice)
{"Lowest Capacity Asset", "IBM R735QTJ8XC9X"},
{"Portfolio Turnover", "39.89%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "32f56b0f4e9300ef1a34464e8083c7e7"}
+ {"OrderListHash", "d2af4746a4d01ca4d0ce0b0c44f30451"}
};
}
}
diff --git a/Algorithm.CSharp/EuropeanOptionsCannotBeExercisedBeforeExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/EuropeanOptionsCannotBeExercisedBeforeExpiryRegressionAlgorithm.cs
index 9b8c72812632..3f9ce0cc1038 100644
--- a/Algorithm.CSharp/EuropeanOptionsCannotBeExercisedBeforeExpiryRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/EuropeanOptionsCannotBeExercisedBeforeExpiryRegressionAlgorithm.cs
@@ -160,33 +160,33 @@ public override void OnEndOfAlgorithm()
public Dictionary ExpectedStatistics => new Dictionary
{
{"Total Orders", "2"},
- {"Average Win", "0.68%"},
+ {"Average Win", "2.19%"},
{"Average Loss", "0%"},
- {"Compounding Annual Return", "24.075%"},
- {"Drawdown", "1.900%"},
+ {"Compounding Annual Return", "100.016%"},
+ {"Drawdown", "3.600%"},
{"Expectancy", "0"},
{"Start Equity", "200000"},
- {"End Equity", "201354"},
- {"Net Profit", "0.677%"},
- {"Sharpe Ratio", "5.76"},
+ {"End Equity", "204384"},
+ {"Net Profit", "2.192%"},
+ {"Sharpe Ratio", "9.169"},
{"Sortino Ratio", "0"},
- {"Probabilistic Sharpe Ratio", "89.644%"},
+ {"Probabilistic Sharpe Ratio", "92.918%"},
{"Loss Rate", "0%"},
{"Win Rate", "100%"},
{"Profit-Loss Ratio", "0"},
- {"Alpha", "0.946"},
- {"Beta", "-0.354"},
- {"Annual Standard Deviation", "0.123"},
- {"Annual Variance", "0.015"},
- {"Information Ratio", "0.211"},
- {"Tracking Error", "0.176"},
- {"Treynor Ratio", "-2.004"},
+ {"Alpha", "3.002"},
+ {"Beta", "-0.818"},
+ {"Annual Standard Deviation", "0.268"},
+ {"Annual Variance", "0.072"},
+ {"Information Ratio", "5.749"},
+ {"Tracking Error", "0.31"},
+ {"Treynor Ratio", "-2.999"},
{"Total Fees", "$0.00"},
- {"Estimated Strategy Capacity", "$1700000.00"},
- {"Lowest Capacity Asset", "SPX XL80P3HB5O6M|SPX 31"},
- {"Portfolio Turnover", "0.35%"},
+ {"Estimated Strategy Capacity", "$420000.00"},
+ {"Lowest Capacity Asset", "SPX XL80P3GHIA9A|SPX 31"},
+ {"Portfolio Turnover", "2.37%"},
{"Drawdown Recovery", "10"},
- {"OrderListHash", "c511179c15aa167365cc1acb91b20bf3"}
+ {"OrderListHash", "0d2ccc2fdfa2b81bf71361c8248c4a59"}
};
}
}
diff --git a/Algorithm.CSharp/FeeModelNotUsingAccountCurrency.cs b/Algorithm.CSharp/FeeModelNotUsingAccountCurrency.cs
index 37a7b086d104..9b62692c94f9 100644
--- a/Algorithm.CSharp/FeeModelNotUsingAccountCurrency.cs
+++ b/Algorithm.CSharp/FeeModelNotUsingAccountCurrency.cs
@@ -157,7 +157,7 @@ public override OrderFee GetOrderFee(OrderFeeParameters parameters)
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 120;
+ public int AlgorithmHistoryDataPoints => 10;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/FillOutsideHoursTickResolutionAlgorithm.cs b/Algorithm.CSharp/FillOutsideHoursTickResolutionAlgorithm.cs
index d5a7a5135e76..98c5dc69db51 100644
--- a/Algorithm.CSharp/FillOutsideHoursTickResolutionAlgorithm.cs
+++ b/Algorithm.CSharp/FillOutsideHoursTickResolutionAlgorithm.cs
@@ -85,7 +85,7 @@ public class FillOutsideHoursTickResolutionAlgorithm : FillOutsideHoursMinuteRes
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
{"Portfolio Turnover", "0.07%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "098dfba7feaa7389ceb7630aa7da2cfa"}
+ {"OrderListHash", "baab871855df123de17fb010951f55da"}
};
}
}
diff --git a/Algorithm.CSharp/ForexInternalFeedOnDataHigherResolutionRegressionAlgorithm.cs b/Algorithm.CSharp/ForexInternalFeedOnDataHigherResolutionRegressionAlgorithm.cs
index 67cd5c68356d..351c702226e7 100644
--- a/Algorithm.CSharp/ForexInternalFeedOnDataHigherResolutionRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/ForexInternalFeedOnDataHigherResolutionRegressionAlgorithm.cs
@@ -136,12 +136,12 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 63;
+ public long DataPoints => 64;
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 120;
+ public int AlgorithmHistoryDataPoints => 10;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/ForexInternalFeedOnDataSameResolutionRegressionAlgorithm.cs b/Algorithm.CSharp/ForexInternalFeedOnDataSameResolutionRegressionAlgorithm.cs
index ca10ee0aaf4d..c405536d0315 100644
--- a/Algorithm.CSharp/ForexInternalFeedOnDataSameResolutionRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/ForexInternalFeedOnDataSameResolutionRegressionAlgorithm.cs
@@ -135,12 +135,12 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 31;
+ public long DataPoints => 32;
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 120;
+ public int AlgorithmHistoryDataPoints => 10;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/ForexMultiResolutionRegressionAlgorithm.cs b/Algorithm.CSharp/ForexMultiResolutionRegressionAlgorithm.cs
index 2bd99298e9ee..9f4d5dea4e4b 100644
--- a/Algorithm.CSharp/ForexMultiResolutionRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/ForexMultiResolutionRegressionAlgorithm.cs
@@ -93,7 +93,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 189;
+ public int AlgorithmHistoryDataPoints => 55;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/FractionalQuantityRegressionAlgorithm.cs b/Algorithm.CSharp/FractionalQuantityRegressionAlgorithm.cs
index 684749ad17ce..da5b1d807ca9 100644
--- a/Algorithm.CSharp/FractionalQuantityRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/FractionalQuantityRegressionAlgorithm.cs
@@ -101,7 +101,7 @@ private void DataConsolidated(object sender, TradeBar e)
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 60;
+ public int AlgorithmHistoryDataPoints => 10;
///
/// Final status of the algorithm
@@ -119,7 +119,7 @@ private void DataConsolidated(object sender, TradeBar e)
{"Compounding Annual Return", "1497.266%"},
{"Drawdown", "5.500%"},
{"Expectancy", "1.339"},
- {"Start Equity", "100000.0"},
+ {"Start Equity", "100000.00"},
{"End Equity", "113775.23"},
{"Net Profit", "13.775%"},
{"Sharpe Ratio", "4.906"},
diff --git a/Algorithm.CSharp/FutureOptionBuySellCallIntradayRegressionAlgorithm.cs b/Algorithm.CSharp/FutureOptionBuySellCallIntradayRegressionAlgorithm.cs
index 91421f786d28..30f7d51069f1 100644
--- a/Algorithm.CSharp/FutureOptionBuySellCallIntradayRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/FutureOptionBuySellCallIntradayRegressionAlgorithm.cs
@@ -112,7 +112,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 309282;
+ public long DataPoints => 309286;
///
/// Data Points count of the algorithm history
@@ -153,10 +153,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "3.785"},
{"Total Fees", "$2.84"},
{"Estimated Strategy Capacity", "$120000000.00"},
- {"Lowest Capacity Asset", "ES XFH59UPBIJ7O|ES XFH59UK0MYO1"},
+ {"Lowest Capacity Asset", "ES XFH59UPBMTJ8|ES XFH59UK0MYO1"},
{"Portfolio Turnover", "3.67%"},
{"Drawdown Recovery", "74"},
- {"OrderListHash", "c4be2f5b6bff9e6fae4a675a973e2f27"}
+ {"OrderListHash", "6e17a52c917383260dcf0345567a1ea9"}
};
}
}
diff --git a/Algorithm.CSharp/FutureOptionCallITMExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/FutureOptionCallITMExpiryRegressionAlgorithm.cs
index d2bf2a388807..f569f7d2140e 100644
--- a/Algorithm.CSharp/FutureOptionCallITMExpiryRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/FutureOptionCallITMExpiryRegressionAlgorithm.cs
@@ -200,7 +200,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 212196;
+ public long DataPoints => 212198;
///
/// Data Points count of the algorithm history
@@ -241,10 +241,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "-21.841"},
{"Total Fees", "$1.42"},
{"Estimated Strategy Capacity", "$120000000.00"},
- {"Lowest Capacity Asset", "ES XFH59UPBIJ7O|ES XFH59UK0MYO1"},
+ {"Lowest Capacity Asset", "ES XFH59UPBMTJ8|ES XFH59UK0MYO1"},
{"Portfolio Turnover", "1.94%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "0fcfb38b639ae544952fd313fbc76077"}
+ {"OrderListHash", "a7d2aa89bb101a77fdbc04890235f83c"}
};
}
}
diff --git a/Algorithm.CSharp/FutureOptionCallITMGreeksExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/FutureOptionCallITMGreeksExpiryRegressionAlgorithm.cs
index de5fc1efe60a..12a2775e3bbb 100644
--- a/Algorithm.CSharp/FutureOptionCallITMGreeksExpiryRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/FutureOptionCallITMGreeksExpiryRegressionAlgorithm.cs
@@ -165,7 +165,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 212196;
+ public long DataPoints => 212198;
///
/// Data Points count of the algorithm history
@@ -206,10 +206,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "-18.59"},
{"Total Fees", "$7.10"},
{"Estimated Strategy Capacity", "$24000000.00"},
- {"Lowest Capacity Asset", "ES XFH59UPBIJ7O|ES XFH59UK0MYO1"},
+ {"Lowest Capacity Asset", "ES XFH59UPBMTJ8|ES XFH59UK0MYO1"},
{"Portfolio Turnover", "12.22%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "355dbab2e93d7a62b073b6e6cd4557c2"}
+ {"OrderListHash", "1d4a9403cd69b8510f15d100acdffa26"}
};
}
}
diff --git a/Algorithm.CSharp/FutureOptionCallOTMExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/FutureOptionCallOTMExpiryRegressionAlgorithm.cs
index 303f518fa80a..2225385ab1c4 100644
--- a/Algorithm.CSharp/FutureOptionCallOTMExpiryRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/FutureOptionCallOTMExpiryRegressionAlgorithm.cs
@@ -176,7 +176,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 212196;
+ public long DataPoints => 212198;
///
/// Data Points count of the algorithm history
@@ -217,10 +217,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "-23.065"},
{"Total Fees", "$1.42"},
{"Estimated Strategy Capacity", "$180000000.00"},
- {"Lowest Capacity Asset", "ES XFH59UPHGV9G|ES XFH59UK0MYO1"},
+ {"Lowest Capacity Asset", "ES XFH59UPHL5L0|ES XFH59UK0MYO1"},
{"Portfolio Turnover", "0.02%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "1d3c36cec32b24e8911d87d7b9730192"}
+ {"OrderListHash", "d84cd529c8535b576d63c0f9c29635c3"}
};
}
}
diff --git a/Algorithm.CSharp/FutureOptionChainFullDataRegressionAlgorithm.cs b/Algorithm.CSharp/FutureOptionChainFullDataRegressionAlgorithm.cs
index c6a9984a1911..970699ae6d2e 100644
--- a/Algorithm.CSharp/FutureOptionChainFullDataRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/FutureOptionChainFullDataRegressionAlgorithm.cs
@@ -119,10 +119,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$34601.14"},
{"Estimated Strategy Capacity", "$0"},
- {"Lowest Capacity Asset", "ES XCZJLCGM383O|ES XCZJLC9NOB29"},
+ {"Lowest Capacity Asset", "ES XCZJLCGM7IF8|ES XCZJLC9NOB29"},
{"Portfolio Turnover", "112.25%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "2bef4eb69857dcfbda06009e2b712ac2"}
+ {"OrderListHash", "4000aa7b360b9146b9f184d0cc188980"}
};
}
}
diff --git a/Algorithm.CSharp/FutureOptionChainsMultipleFullDataRegressionAlgorithm.cs b/Algorithm.CSharp/FutureOptionChainsMultipleFullDataRegressionAlgorithm.cs
index 48d529f7d648..a2fb0a1903a3 100644
--- a/Algorithm.CSharp/FutureOptionChainsMultipleFullDataRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/FutureOptionChainsMultipleFullDataRegressionAlgorithm.cs
@@ -139,10 +139,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$19016.64"},
{"Estimated Strategy Capacity", "$0"},
- {"Lowest Capacity Asset", "ES XCZJLCGM383O|ES XCZJLC9NOB29"},
+ {"Lowest Capacity Asset", "ES XCZJLCGM7IF8|ES XCZJLC9NOB29"},
{"Portfolio Turnover", "49.52%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "4e1e5bc330f892d94a23a887d002133e"}
+ {"OrderListHash", "8ef148c1100cb53bdd6a833c7a958974"}
};
}
}
diff --git a/Algorithm.CSharp/FutureOptionDailyRegressionAlgorithm.cs b/Algorithm.CSharp/FutureOptionDailyRegressionAlgorithm.cs
index 1fda2484099c..7267e6cd17bc 100644
--- a/Algorithm.CSharp/FutureOptionDailyRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/FutureOptionDailyRegressionAlgorithm.cs
@@ -159,10 +159,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "0"},
{"Total Fees", "$2.84"},
{"Estimated Strategy Capacity", "$0"},
- {"Lowest Capacity Asset", "ES XCZJLCEYJVLW|ES XCZJLC9NOB29"},
+ {"Lowest Capacity Asset", "ES XCZJLCEYO5XG|ES XCZJLC9NOB29"},
{"Portfolio Turnover", "4.24%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "3917ccec8393e2505e9a5183bccfd237"}
+ {"OrderListHash", "ea4b22620e9435d7fa80888b8bd7be87"}
};
}
}
diff --git a/Algorithm.CSharp/FutureOptionHourlyRegressionAlgorithm.cs b/Algorithm.CSharp/FutureOptionHourlyRegressionAlgorithm.cs
index 8f768898fd53..0a91efe93c1f 100644
--- a/Algorithm.CSharp/FutureOptionHourlyRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/FutureOptionHourlyRegressionAlgorithm.cs
@@ -104,10 +104,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$2.84"},
{"Estimated Strategy Capacity", "$3000.00"},
- {"Lowest Capacity Asset", "ES XCZJLCEYJVLW|ES XCZJLC9NOB29"},
+ {"Lowest Capacity Asset", "ES XCZJLCEYO5XG|ES XCZJLC9NOB29"},
{"Portfolio Turnover", "4.90%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "66d11399fe18d95de2821f2e456500ab"}
+ {"OrderListHash", "10661c6d84f71ca7e07e2fdf5b79851b"}
};
}
}
diff --git a/Algorithm.CSharp/FutureOptionMultipleContractsInDifferentContractMonthsWithSameUnderlyingFutureRegressionAlgorithm.cs b/Algorithm.CSharp/FutureOptionMultipleContractsInDifferentContractMonthsWithSameUnderlyingFutureRegressionAlgorithm.cs
index 8a9a8fcfa3c2..f3f8d0968b54 100644
--- a/Algorithm.CSharp/FutureOptionMultipleContractsInDifferentContractMonthsWithSameUnderlyingFutureRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/FutureOptionMultipleContractsInDifferentContractMonthsWithSameUnderlyingFutureRegressionAlgorithm.cs
@@ -150,10 +150,10 @@ private static Symbol CreateOption(DateTime expiry, OptionRight optionRight, dec
{"Treynor Ratio", "0.451"},
{"Total Fees", "$9.88"},
{"Estimated Strategy Capacity", "$31000000.00"},
- {"Lowest Capacity Asset", "OG 31BFX0QKBVPGG|GC XE1Y0ZJ8NQ8T"},
+ {"Lowest Capacity Asset", "OG 31BFX0QKBZZS0|GC XE1Y0ZJ8NQ8T"},
{"Portfolio Turnover", "2.65%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "06e076b1b516ea2c7a67401867467740"}
+ {"OrderListHash", "9b619fad030ef229690386aabbaedb4d"}
};
}
}
diff --git a/Algorithm.CSharp/FutureOptionPutITMExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/FutureOptionPutITMExpiryRegressionAlgorithm.cs
index 195a0da6cab9..f76a2c2b166d 100644
--- a/Algorithm.CSharp/FutureOptionPutITMExpiryRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/FutureOptionPutITMExpiryRegressionAlgorithm.cs
@@ -201,7 +201,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 212196;
+ public long DataPoints => 212198;
///
/// Data Points count of the algorithm history
@@ -242,10 +242,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "-36.3"},
{"Total Fees", "$1.42"},
{"Estimated Strategy Capacity", "$79000000.00"},
- {"Lowest Capacity Asset", "ES 31EL5FAOOQON8|ES XFH59UK0MYO1"},
+ {"Lowest Capacity Asset", "ES 31EL5FAOOUYYS|ES XFH59UK0MYO1"},
{"Portfolio Turnover", "1.98%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "20da5994dd627b414fb7b589eefa4d5c"}
+ {"OrderListHash", "a4de58a3a31739f593c8a1ed099bad10"}
};
}
}
diff --git a/Algorithm.CSharp/FutureOptionPutOTMExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/FutureOptionPutOTMExpiryRegressionAlgorithm.cs
index 7749e276aa90..8abe7d085383 100644
--- a/Algorithm.CSharp/FutureOptionPutOTMExpiryRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/FutureOptionPutOTMExpiryRegressionAlgorithm.cs
@@ -174,7 +174,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 212196;
+ public long DataPoints => 212198;
///
/// Data Points count of the algorithm history
@@ -215,10 +215,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "-32.556"},
{"Total Fees", "$1.42"},
{"Estimated Strategy Capacity", "$290000000.00"},
- {"Lowest Capacity Asset", "ES 31EL5FBZBMXES|ES XFH59UK0MYO1"},
+ {"Lowest Capacity Asset", "ES 31EL5FBZBR7QC|ES XFH59UK0MYO1"},
{"Portfolio Turnover", "0.03%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "c00499f16e60faf91708e5c1c4fcf851"}
+ {"OrderListHash", "01fc084078bdca7ec7d409f7bb398c14"}
};
}
}
diff --git a/Algorithm.CSharp/FutureOptionShortCallITMExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/FutureOptionShortCallITMExpiryRegressionAlgorithm.cs
index 6171e8e877fc..daf89dbb3b41 100644
--- a/Algorithm.CSharp/FutureOptionShortCallITMExpiryRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/FutureOptionShortCallITMExpiryRegressionAlgorithm.cs
@@ -185,7 +185,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 212196;
+ public long DataPoints => 212198;
///
/// Data Points count of the algorithm history
@@ -226,10 +226,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "-13.127"},
{"Total Fees", "$1.42"},
{"Estimated Strategy Capacity", "$13000000.00"},
- {"Lowest Capacity Asset", "ES XFH59UP5K75W|ES XFH59UK0MYO1"},
+ {"Lowest Capacity Asset", "ES XFH59UP5OHHG|ES XFH59UK0MYO1"},
{"Portfolio Turnover", "1.79%"},
{"Drawdown Recovery", "165"},
- {"OrderListHash", "ea7c72a493aa29a52a5f782fc741d391"}
+ {"OrderListHash", "51a7c148e25c56692d0ed5971483f04d"}
};
}
}
diff --git a/Algorithm.CSharp/FutureOptionShortCallOTMExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/FutureOptionShortCallOTMExpiryRegressionAlgorithm.cs
index 2f2fbf4c2a70..d1e49db4e09d 100644
--- a/Algorithm.CSharp/FutureOptionShortCallOTMExpiryRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/FutureOptionShortCallOTMExpiryRegressionAlgorithm.cs
@@ -168,7 +168,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 212196;
+ public long DataPoints => 212198;
///
/// Data Points count of the algorithm history
@@ -209,10 +209,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "-11.048"},
{"Total Fees", "$1.42"},
{"Estimated Strategy Capacity", "$100000000.00"},
- {"Lowest Capacity Asset", "ES XFH59UPNF7B8|ES XFH59UK0MYO1"},
+ {"Lowest Capacity Asset", "ES XFH59UPNJHMS|ES XFH59UK0MYO1"},
{"Portfolio Turnover", "0.01%"},
{"Drawdown Recovery", "165"},
- {"OrderListHash", "2b83fbaa9c10a1a9c65ecd779bd40b94"}
+ {"OrderListHash", "3e39f8bdb373b371999835fbf680eef8"}
};
}
}
diff --git a/Algorithm.CSharp/FutureOptionShortPutITMExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/FutureOptionShortPutITMExpiryRegressionAlgorithm.cs
index 2f6987508d2a..99a75a59b56e 100644
--- a/Algorithm.CSharp/FutureOptionShortPutITMExpiryRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/FutureOptionShortPutITMExpiryRegressionAlgorithm.cs
@@ -182,7 +182,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 212196;
+ public long DataPoints => 212198;
///
/// Data Points count of the algorithm history
@@ -223,10 +223,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "-41.831"},
{"Total Fees", "$1.42"},
{"Estimated Strategy Capacity", "$12000000.00"},
- {"Lowest Capacity Asset", "ES 31EL5FAOUP0P0|ES XFH59UK0MYO1"},
+ {"Lowest Capacity Asset", "ES 31EL5FAOUTB0K|ES XFH59UK0MYO1"},
{"Portfolio Turnover", "1.87%"},
{"Drawdown Recovery", "165"},
- {"OrderListHash", "cc0e2d8195b87d37b842de7224eac8f0"}
+ {"OrderListHash", "3ced70635b9a6a1ff260a0f8706e9fff"}
};
}
}
diff --git a/Algorithm.CSharp/FutureOptionShortPutOTMExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/FutureOptionShortPutOTMExpiryRegressionAlgorithm.cs
index 16df8db5397e..7fb1e141f109 100644
--- a/Algorithm.CSharp/FutureOptionShortPutOTMExpiryRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/FutureOptionShortPutOTMExpiryRegressionAlgorithm.cs
@@ -167,7 +167,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 212196;
+ public long DataPoints => 212198;
///
/// Data Points count of the algorithm history
@@ -208,10 +208,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "-24.076"},
{"Total Fees", "$1.42"},
{"Estimated Strategy Capacity", "$110000000.00"},
- {"Lowest Capacity Asset", "ES 31EL5FAJQ6SBO|ES XFH59UK0MYO1"},
+ {"Lowest Capacity Asset", "ES 31EL5FAJQB2N8|ES XFH59UK0MYO1"},
{"Portfolio Turnover", "0.02%"},
{"Drawdown Recovery", "165"},
- {"OrderListHash", "a4f512c607cf1ec56f3d76ede17728dd"}
+ {"OrderListHash", "ddc3a9d7483eb53bac7313682f4b7d0f"}
};
}
}
diff --git a/Algorithm.CSharp/FuturesAndFuturesOptionsExpiryTimeAndLiquidationRegressionAlgorithm.cs b/Algorithm.CSharp/FuturesAndFuturesOptionsExpiryTimeAndLiquidationRegressionAlgorithm.cs
index 3f803da513f9..ab85a2583e82 100644
--- a/Algorithm.CSharp/FuturesAndFuturesOptionsExpiryTimeAndLiquidationRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/FuturesAndFuturesOptionsExpiryTimeAndLiquidationRegressionAlgorithm.cs
@@ -178,7 +178,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 212942;
+ public long DataPoints => 212944;
///
/// Data Points count of the algorithm history
@@ -222,7 +222,7 @@ public override void OnEndOfAlgorithm()
{"Lowest Capacity Asset", "ES XFH59UK0MYO1"},
{"Portfolio Turnover", "1.04%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "873800e40d1b38b08fc1764cd578bb4a"}
+ {"OrderListHash", "6ef08dcc3239de1821ecaa4bbdee41ab"}
};
}
}
diff --git a/Algorithm.CSharp/FuturesAutomaticSeedRegressionAlgorithm.cs b/Algorithm.CSharp/FuturesAutomaticSeedRegressionAlgorithm.cs
new file mode 100644
index 000000000000..e6233f05cdd9
--- /dev/null
+++ b/Algorithm.CSharp/FuturesAutomaticSeedRegressionAlgorithm.cs
@@ -0,0 +1,87 @@
+/*
+ * 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 QuantConnect.Data.UniverseSelection;
+using QuantConnect.Securities;
+
+namespace QuantConnect.Algorithm.CSharp
+{
+ ///
+ /// Regression algorithm asserting that futures and future option contracts added via universe selection
+ /// get automatically seeded by default
+ ///
+ public class FuturesAutomaticSeedRegressionAlgorithm : AutomaticSeedBaseRegressionAlgorithm
+ {
+ private bool _futureContractsAdded;
+ private bool _fopsContractsAdded;
+
+ protected override bool ShouldHaveTradeData => true;
+ protected override bool ShouldHaveQuoteData => false;
+ protected override bool ShouldHaveOpenInterestData => true;
+
+ public override void Initialize()
+ {
+ SetStartDate(2020, 01, 07);
+ SetEndDate(2020, 01, 07);
+ SetCash(100000);
+
+ Settings.SeedInitialPrices = true;
+
+ var futures = AddFuture(Futures.Indices.SP500EMini);
+ futures.SetFilter(0, 365);
+
+ AddFutureOption(futures.Symbol, universe => universe.Strikes(-5, +5));
+ }
+
+ public override void OnSecuritiesChanged(SecurityChanges changes)
+ {
+ base.OnSecuritiesChanged(changes);
+
+ if (!_futureContractsAdded || !_fopsContractsAdded)
+ {
+ foreach (var addedSecurity in changes.AddedSecurities)
+ {
+ // Just making sure we had the data to select and seed futures and future options
+ _futureContractsAdded |= addedSecurity.Symbol.SecurityType == SecurityType.Future;
+ _fopsContractsAdded |= addedSecurity.Symbol.SecurityType == SecurityType.FutureOption;
+ }
+ }
+ }
+
+ public override void OnEndOfAlgorithm()
+ {
+ if (!_futureContractsAdded)
+ {
+ throw new RegressionTestException("No option contracts were added");
+ }
+
+ if (!_fopsContractsAdded)
+ {
+ throw new RegressionTestException("No future option contracts were added");
+ }
+ }
+
+ ///
+ /// Data Points count of all timeslices of algorithm
+ ///
+ public override long DataPoints => 448;
+
+ ///
+ /// Data Points count of the algorithm history
+ ///
+ public override int AlgorithmHistoryDataPoints => 453;
+ }
+}
diff --git a/Algorithm.CSharp/HSIFutureDailyRegressionAlgorithm.cs b/Algorithm.CSharp/HSIFutureDailyRegressionAlgorithm.cs
index 2529ddccfa1c..2c851fdfc754 100644
--- a/Algorithm.CSharp/HSIFutureDailyRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/HSIFutureDailyRegressionAlgorithm.cs
@@ -36,7 +36,7 @@ public class HSIFutureDailyRegressionAlgorithm : HSIFutureHourRegressionAlgorith
///
/// Data Points count of the algorithm history
///
- public override int AlgorithmHistoryDataPoints => 17;
+ public override int AlgorithmHistoryDataPoints => 115;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/HSIFutureHourRegressionAlgorithm.cs b/Algorithm.CSharp/HSIFutureHourRegressionAlgorithm.cs
index 637b42ed7b31..7cc7211d1371 100644
--- a/Algorithm.CSharp/HSIFutureHourRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/HSIFutureHourRegressionAlgorithm.cs
@@ -166,7 +166,7 @@ public override void OnSecuritiesChanged(SecurityChanges changes)
///
/// Data Points count of the algorithm history
///
- public virtual int AlgorithmHistoryDataPoints => 30;
+ public virtual int AlgorithmHistoryDataPoints => 133;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/HistoryProviderManagerRegressionAlgorithm.cs b/Algorithm.CSharp/HistoryProviderManagerRegressionAlgorithm.cs
index 07499a1fd0ad..1490fd859681 100644
--- a/Algorithm.CSharp/HistoryProviderManagerRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/HistoryProviderManagerRegressionAlgorithm.cs
@@ -77,7 +77,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 14061;
+ public int AlgorithmHistoryDataPoints => 100;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/ImmediateExecutionModelWorksWithBinanceFeeModel.cs b/Algorithm.CSharp/ImmediateExecutionModelWorksWithBinanceFeeModel.cs
index fcd4655a458b..d6a75735c42e 100644
--- a/Algorithm.CSharp/ImmediateExecutionModelWorksWithBinanceFeeModel.cs
+++ b/Algorithm.CSharp/ImmediateExecutionModelWorksWithBinanceFeeModel.cs
@@ -75,7 +75,7 @@ public override void OnOrderEvent(OrderEvent orderEvent)
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 60;
+ public int AlgorithmHistoryDataPoints => 5;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/IndexOptionBuySellCallIntradayRegressionAlgorithm.cs b/Algorithm.CSharp/IndexOptionBuySellCallIntradayRegressionAlgorithm.cs
index 960e03d52d7c..f85442ad3521 100644
--- a/Algorithm.CSharp/IndexOptionBuySellCallIntradayRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/IndexOptionBuySellCallIntradayRegressionAlgorithm.cs
@@ -118,7 +118,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 32143;
+ public long DataPoints => 32144;
///
/// Data Points count of the algorithm history
@@ -159,10 +159,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "3.118"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
- {"Lowest Capacity Asset", "SPX XL80P3HB5O6M|SPX 31"},
+ {"Lowest Capacity Asset", "SPX XL80P3HB9YI6|SPX 31"},
{"Portfolio Turnover", "0.51%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "ff967a551873aa872879d0a11d043679"}
+ {"OrderListHash", "9237e1fd3cf099a47a2adae18f91aa2f"}
};
}
}
diff --git a/Algorithm.CSharp/IndexOptionCallITMExpiryDailyRegressionAlgorithm.cs b/Algorithm.CSharp/IndexOptionCallITMExpiryDailyRegressionAlgorithm.cs
index 3e2abc926a20..470c0d737abe 100644
--- a/Algorithm.CSharp/IndexOptionCallITMExpiryDailyRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/IndexOptionCallITMExpiryDailyRegressionAlgorithm.cs
@@ -38,7 +38,7 @@ public override void Initialize()
///
/// Data Points count of all timeslices of algorithm
///
- public override long DataPoints => 195;
+ public override long DataPoints => 196;
///
/// Data Points count of the algorithm history
@@ -74,10 +74,10 @@ public override void Initialize()
{"Treynor Ratio", "-7.99"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
- {"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
+ {"Lowest Capacity Asset", "SPX XL80P3GHIA9A|SPX 31"},
{"Portfolio Turnover", "1.90%"},
{"Drawdown Recovery", "9"},
- {"OrderListHash", "fce4ce6f25578a0ec8e7efa272b2dd02"}
+ {"OrderListHash", "b02af3819f796241269614e0ebf49964"}
};
}
}
diff --git a/Algorithm.CSharp/IndexOptionCallITMExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/IndexOptionCallITMExpiryRegressionAlgorithm.cs
index b1d352df2867..dd29a2052f9f 100644
--- a/Algorithm.CSharp/IndexOptionCallITMExpiryRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/IndexOptionCallITMExpiryRegressionAlgorithm.cs
@@ -170,7 +170,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public virtual long DataPoints => 19908;
+ public virtual long DataPoints => 19909;
///
/// Data Points count of the algorithm history
@@ -211,10 +211,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "-7.347"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
- {"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
+ {"Lowest Capacity Asset", "SPX XL80P3GHIA9A|SPX 31"},
{"Portfolio Turnover", "1.95%"},
{"Drawdown Recovery", "9"},
- {"OrderListHash", "da367473fff3a12856ba2194d2bb2006"}
+ {"OrderListHash", "59551fdea61b6d4436ffd4a60aed1f40"}
};
}
}
diff --git a/Algorithm.CSharp/IndexOptionCallITMGreeksExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/IndexOptionCallITMGreeksExpiryRegressionAlgorithm.cs
index 9983b1e39f6e..77a743213691 100644
--- a/Algorithm.CSharp/IndexOptionCallITMGreeksExpiryRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/IndexOptionCallITMGreeksExpiryRegressionAlgorithm.cs
@@ -156,7 +156,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 19908;
+ public long DataPoints => 19909;
///
/// Data Points count of the algorithm history
@@ -197,10 +197,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "-8.141"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$59000000.00"},
- {"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
+ {"Lowest Capacity Asset", "SPX XL80P3GHIA9A|SPX 31"},
{"Portfolio Turnover", "2.19%"},
{"Drawdown Recovery", "9"},
- {"OrderListHash", "1a742c2ab3442846f82ddb3728f814ef"}
+ {"OrderListHash", "5b8ec5478b149dc9adfb09ea6407af82"}
};
}
}
diff --git a/Algorithm.CSharp/IndexOptionCallOTMExpiryDailyRegressionAlgorithm.cs b/Algorithm.CSharp/IndexOptionCallOTMExpiryDailyRegressionAlgorithm.cs
index 50931610ec93..a31b987ebb34 100644
--- a/Algorithm.CSharp/IndexOptionCallOTMExpiryDailyRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/IndexOptionCallOTMExpiryDailyRegressionAlgorithm.cs
@@ -38,7 +38,7 @@ public override void Initialize()
///
/// Data Points count of all timeslices of algorithm
///
- public override long DataPoints => 185;
+ public override long DataPoints => 186;
///
/// Data Points count of the algorithm history
@@ -74,10 +74,10 @@ public override void Initialize()
{"Treynor Ratio", "-32.969"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
- {"Lowest Capacity Asset", "SPX XL80P59H5E6M|SPX 31"},
+ {"Lowest Capacity Asset", "SPX XL80P59H9OI6|SPX 31"},
{"Portfolio Turnover", "0.00%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "adfa67772fb1a7f40d65922cbe180c8e"}
+ {"OrderListHash", "0a8db8bba3b2198ba4675fc909426c35"}
};
}
}
diff --git a/Algorithm.CSharp/IndexOptionCallOTMExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/IndexOptionCallOTMExpiryRegressionAlgorithm.cs
index 02e5a96e0fee..1b42c4bacf34 100644
--- a/Algorithm.CSharp/IndexOptionCallOTMExpiryRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/IndexOptionCallOTMExpiryRegressionAlgorithm.cs
@@ -178,7 +178,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public virtual long DataPoints => 15941;
+ public virtual long DataPoints => 15942;
///
/// Data Points count of the algorithm history
@@ -219,10 +219,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "-32.969"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$22000.00"},
- {"Lowest Capacity Asset", "SPX XL80P59H5E6M|SPX 31"},
+ {"Lowest Capacity Asset", "SPX XL80P59H9OI6|SPX 31"},
{"Portfolio Turnover", "0.00%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "adfa67772fb1a7f40d65922cbe180c8e"}
+ {"OrderListHash", "0a8db8bba3b2198ba4675fc909426c35"}
};
}
}
diff --git a/Algorithm.CSharp/IndexOptionChainApisConsistencyRegressionAlgorithm.cs b/Algorithm.CSharp/IndexOptionChainApisConsistencyRegressionAlgorithm.cs
index b6a759012d6e..d5b6c4b78931 100644
--- a/Algorithm.CSharp/IndexOptionChainApisConsistencyRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/IndexOptionChainApisConsistencyRegressionAlgorithm.cs
@@ -36,5 +36,10 @@ protected override Option GetOption()
/// Data Points count of all timeslices of algorithm
///
public override long DataPoints => 2862;
+
+ ///
+ /// Data Points count of the algorithm history
+ ///
+ public override int AlgorithmHistoryDataPoints => 2;
}
}
diff --git a/Algorithm.CSharp/IndexOptionPutITMExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/IndexOptionPutITMExpiryRegressionAlgorithm.cs
index a40c5989f733..c3ac8a75e13c 100644
--- a/Algorithm.CSharp/IndexOptionPutITMExpiryRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/IndexOptionPutITMExpiryRegressionAlgorithm.cs
@@ -185,7 +185,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 19890;
+ public long DataPoints => 19891;
///
/// Data Points count of the algorithm history
@@ -226,10 +226,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "-3.216"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
- {"Lowest Capacity Asset", "SPX 31KC0UJHC75TA|SPX 31"},
+ {"Lowest Capacity Asset", "SPX 31KC0UJHCBG4U|SPX 31"},
{"Portfolio Turnover", "1.94%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "318a374cfedd073d468f69c53f827323"}
+ {"OrderListHash", "3f315a4d5124203fb8ed466926314824"}
};
}
}
diff --git a/Algorithm.CSharp/IndexOptionPutOTMExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/IndexOptionPutOTMExpiryRegressionAlgorithm.cs
index 20c7e750a1c9..399d03431b81 100644
--- a/Algorithm.CSharp/IndexOptionPutOTMExpiryRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/IndexOptionPutOTMExpiryRegressionAlgorithm.cs
@@ -169,7 +169,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 19984;
+ public long DataPoints => 19985;
///
/// Data Points count of the algorithm history
@@ -210,10 +210,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "-5.965"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
- {"Lowest Capacity Asset", "SPX 31KC0UJFONTBI|SPX 31"},
+ {"Lowest Capacity Asset", "SPX 31KC0UJFOS3N2|SPX 31"},
{"Portfolio Turnover", "0.01%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "2a1eac1c8ef2e2696a7390231fc6073d"}
+ {"OrderListHash", "22c6e3e24145b1d57ef6a7f2b30108a7"}
};
}
}
diff --git a/Algorithm.CSharp/IndexOptionScaledStrikeRegressionAlgorithm.cs b/Algorithm.CSharp/IndexOptionScaledStrikeRegressionAlgorithm.cs
index 0dd64dd58b86..de392d6ae6ec 100644
--- a/Algorithm.CSharp/IndexOptionScaledStrikeRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/IndexOptionScaledStrikeRegressionAlgorithm.cs
@@ -150,10 +150,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "1.7351225556608623E+28"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$7000.00"},
- {"Lowest Capacity Asset", "NQX 31M220FF62ZSE|NDX 31"},
+ {"Lowest Capacity Asset", "NQX 31M220FF67A3Y|NDX 31"},
{"Portfolio Turnover", "6.40%"},
{"Drawdown Recovery", "1"},
- {"OrderListHash", "0de4f8d2fcbb87307e5fe01c060dd44a"}
+ {"OrderListHash", "bbdd7eb2f738326a6184bc71d435c6cb"}
};
}
}
diff --git a/Algorithm.CSharp/IndexOptionShortCallITMExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/IndexOptionShortCallITMExpiryRegressionAlgorithm.cs
index 594c18540930..91f0feb9ead6 100644
--- a/Algorithm.CSharp/IndexOptionShortCallITMExpiryRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/IndexOptionShortCallITMExpiryRegressionAlgorithm.cs
@@ -183,7 +183,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 19908;
+ public long DataPoints => 19909;
///
/// Data Points count of the algorithm history
@@ -224,10 +224,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "-5.019"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
- {"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
+ {"Lowest Capacity Asset", "SPX XL80P3GHIA9A|SPX 31"},
{"Portfolio Turnover", "0.19%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "1b0b0418d3290ea45c38f6c4db8285d2"}
+ {"OrderListHash", "358b15e6d71c9fab8de9f53e667df96e"}
};
}
}
diff --git a/Algorithm.CSharp/IndexOptionShortCallOTMExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/IndexOptionShortCallOTMExpiryRegressionAlgorithm.cs
index 19f8a2cd96fd..b439ff57964b 100644
--- a/Algorithm.CSharp/IndexOptionShortCallOTMExpiryRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/IndexOptionShortCallOTMExpiryRegressionAlgorithm.cs
@@ -163,7 +163,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 15941;
+ public long DataPoints => 15942;
///
/// Data Points count of the algorithm history
@@ -204,10 +204,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "14.02"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$22000.00"},
- {"Lowest Capacity Asset", "SPX XL80P59H5E6M|SPX 31"},
+ {"Lowest Capacity Asset", "SPX XL80P59H9OI6|SPX 31"},
{"Portfolio Turnover", "0.00%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "0b702d78062c1c50372b42bcd6ed2981"}
+ {"OrderListHash", "b2d0a0970bfbb57c5b20d251b0366e29"}
};
}
}
diff --git a/Algorithm.CSharp/IndexOptionShortPutITMExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/IndexOptionShortPutITMExpiryRegressionAlgorithm.cs
index f74354365829..84b872f11072 100644
--- a/Algorithm.CSharp/IndexOptionShortPutITMExpiryRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/IndexOptionShortPutITMExpiryRegressionAlgorithm.cs
@@ -186,7 +186,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 19890;
+ public long DataPoints => 19891;
///
/// Data Points count of the algorithm history
@@ -227,10 +227,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "-4.521"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
- {"Lowest Capacity Asset", "SPX 31KC0UJHC75TA|SPX 31"},
+ {"Lowest Capacity Asset", "SPX 31KC0UJHCBG4U|SPX 31"},
{"Portfolio Turnover", "0.19%"},
{"Drawdown Recovery", "9"},
- {"OrderListHash", "5fa3290876b6616eb338fedccd65fd6f"}
+ {"OrderListHash", "86a79c56040bedf9067b7255131e0387"}
};
}
}
diff --git a/Algorithm.CSharp/IndexOptionShortPutOTMExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/IndexOptionShortPutOTMExpiryRegressionAlgorithm.cs
index 6a48dcea77fe..76d7e117ecc3 100644
--- a/Algorithm.CSharp/IndexOptionShortPutOTMExpiryRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/IndexOptionShortPutOTMExpiryRegressionAlgorithm.cs
@@ -162,7 +162,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 19984;
+ public long DataPoints => 19985;
///
/// Data Points count of the algorithm history
@@ -203,10 +203,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "-4.22"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
- {"Lowest Capacity Asset", "SPX 31KC0UJFONTBI|SPX 31"},
+ {"Lowest Capacity Asset", "SPX 31KC0UJFOS3N2|SPX 31"},
{"Portfolio Turnover", "0.01%"},
{"Drawdown Recovery", "9"},
- {"OrderListHash", "b11d26454cf946dae38b484863698248"}
+ {"OrderListHash", "0b39fcedbea77ba71bf0d4547a3b8fc5"}
};
}
}
diff --git a/Algorithm.CSharp/IndexSecurityCanBeTradableRegressionAlgorithm.cs b/Algorithm.CSharp/IndexSecurityCanBeTradableRegressionAlgorithm.cs
index 89bb566fcad4..960d01fa5cde 100644
--- a/Algorithm.CSharp/IndexSecurityCanBeTradableRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/IndexSecurityCanBeTradableRegressionAlgorithm.cs
@@ -106,7 +106,7 @@ private void AssertIndexIsNotTradable()
///
/// Data Points count of all timeslices of algorithm
///
- public virtual long DataPoints => 796;
+ public virtual long DataPoints => 797;
///
/// Data Points count of the algorithm history
diff --git a/Algorithm.CSharp/IndicatorSelectorsWorkWithDifferentOptions.cs b/Algorithm.CSharp/IndicatorSelectorsWorkWithDifferentOptions.cs
index d16d5f66607e..95c949c52b57 100644
--- a/Algorithm.CSharp/IndicatorSelectorsWorkWithDifferentOptions.cs
+++ b/Algorithm.CSharp/IndicatorSelectorsWorkWithDifferentOptions.cs
@@ -186,12 +186,12 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 454077;
+ public long DataPoints => 455371;
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 351;
+ public int AlgorithmHistoryDataPoints => 296;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/InsufficientBuyingPowerForAutomaticExerciseRegressionAlgorithm.cs b/Algorithm.CSharp/InsufficientBuyingPowerForAutomaticExerciseRegressionAlgorithm.cs
index 0b09371fa80d..86aff0d031be 100644
--- a/Algorithm.CSharp/InsufficientBuyingPowerForAutomaticExerciseRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/InsufficientBuyingPowerForAutomaticExerciseRegressionAlgorithm.cs
@@ -171,7 +171,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 2821;
+ public long DataPoints => 2822;
///
/// Data Points count of the algorithm history
@@ -212,10 +212,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "-0.2"},
{"Total Fees", "$3.30"},
{"Estimated Strategy Capacity", "$2400000.00"},
- {"Lowest Capacity Asset", "GOOCV 305RBQ20WHPNQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 305RBQ20WLZZA|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "54.01%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "97d1c3373a72ec15038949710e7c7a62"}
+ {"OrderListHash", "2f22fc5e9584c2d201b9e0b767a7160d"}
};
}
}
diff --git a/Algorithm.CSharp/InsufficientMarginOrderUpdateRegressionAlgorithm.cs b/Algorithm.CSharp/InsufficientMarginOrderUpdateRegressionAlgorithm.cs
index e20792fb57e4..e71d106cd8cc 100644
--- a/Algorithm.CSharp/InsufficientMarginOrderUpdateRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/InsufficientMarginOrderUpdateRegressionAlgorithm.cs
@@ -159,7 +159,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 60;
+ public int AlgorithmHistoryDataPoints => 5;
///
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
diff --git a/Algorithm.CSharp/InteractiveBrokersBrokerageDisablesIndexOptionsExerciseRegressionAlgorithm.cs b/Algorithm.CSharp/InteractiveBrokersBrokerageDisablesIndexOptionsExerciseRegressionAlgorithm.cs
index 834f61542cf5..0c075b4ce4ec 100644
--- a/Algorithm.CSharp/InteractiveBrokersBrokerageDisablesIndexOptionsExerciseRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/InteractiveBrokersBrokerageDisablesIndexOptionsExerciseRegressionAlgorithm.cs
@@ -163,33 +163,33 @@ public override void OnEndOfAlgorithm()
public Dictionary ExpectedStatistics => new Dictionary
{
{"Total Orders", "3"},
- {"Average Win", "0.68%"},
+ {"Average Win", "2.19%"},
{"Average Loss", "0%"},
- {"Compounding Annual Return", "10.046%"},
- {"Drawdown", "1.900%"},
+ {"Compounding Annual Return", "36.041%"},
+ {"Drawdown", "3.600%"},
{"Expectancy", "0"},
{"Start Equity", "200000"},
- {"End Equity", "201353"},
- {"Net Profit", "0.676%"},
- {"Sharpe Ratio", "3.253"},
+ {"End Equity", "204383"},
+ {"Net Profit", "2.192%"},
+ {"Sharpe Ratio", "4.088"},
{"Sortino Ratio", "0"},
- {"Probabilistic Sharpe Ratio", "86.292%"},
+ {"Probabilistic Sharpe Ratio", "89.872%"},
{"Loss Rate", "0%"},
{"Win Rate", "100%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "0"},
{"Beta", "0"},
- {"Annual Standard Deviation", "0.081"},
- {"Annual Variance", "0.007"},
- {"Information Ratio", "3.284"},
- {"Tracking Error", "0.081"},
+ {"Annual Standard Deviation", "0.177"},
+ {"Annual Variance", "0.031"},
+ {"Information Ratio", "4.102"},
+ {"Tracking Error", "0.177"},
{"Treynor Ratio", "0"},
{"Total Fees", "$1.00"},
- {"Estimated Strategy Capacity", "$1700000.00"},
- {"Lowest Capacity Asset", "SPX XL80P3HB5O6M|SPX 31"},
- {"Portfolio Turnover", "0.16%"},
+ {"Estimated Strategy Capacity", "$420000.00"},
+ {"Lowest Capacity Asset", "SPX XL80P3GHIA9A|SPX 31"},
+ {"Portfolio Turnover", "1.09%"},
{"Drawdown Recovery", "10"},
- {"OrderListHash", "e83502aa04c68dbd42a1f670cd81833f"}
+ {"OrderListHash", "e913c917ccb2641d70e8fffb47df4f02"}
};
}
}
diff --git a/Algorithm.CSharp/InternalSubscriptionHistoryRequestAlgorithm.cs b/Algorithm.CSharp/InternalSubscriptionHistoryRequestAlgorithm.cs
index a4e566250f7e..23bc4ffac59c 100644
--- a/Algorithm.CSharp/InternalSubscriptionHistoryRequestAlgorithm.cs
+++ b/Algorithm.CSharp/InternalSubscriptionHistoryRequestAlgorithm.cs
@@ -80,7 +80,7 @@ public override void OnData(Slice slice)
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 107;
+ public long DataPoints => 108;
///
/// Data Points count of the algorithm history
diff --git a/Algorithm.CSharp/IronCondorStrategyAlgorithm.cs b/Algorithm.CSharp/IronCondorStrategyAlgorithm.cs
index e115837fd860..a714bcb8a633 100644
--- a/Algorithm.CSharp/IronCondorStrategyAlgorithm.cs
+++ b/Algorithm.CSharp/IronCondorStrategyAlgorithm.cs
@@ -160,10 +160,10 @@ protected override void LiquidateStrategy()
{"Treynor Ratio", "0"},
{"Total Fees", "$10.40"},
{"Estimated Strategy Capacity", "$4000.00"},
- {"Lowest Capacity Asset", "GOOCV 306CZL2DIL4G6|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 306CZL2DIPERQ|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "2.00%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "293b5b1c428514fc9d7bb069be75e5e9"}
+ {"OrderListHash", "690651f39abc866e9749e12a1096a79c"}
};
}
}
diff --git a/Algorithm.CSharp/LargeQuantityOptionStrategyAlgorithm.cs b/Algorithm.CSharp/LargeQuantityOptionStrategyAlgorithm.cs
index f1062955a0f2..6223d99983e0 100644
--- a/Algorithm.CSharp/LargeQuantityOptionStrategyAlgorithm.cs
+++ b/Algorithm.CSharp/LargeQuantityOptionStrategyAlgorithm.cs
@@ -44,7 +44,7 @@ public override void Initialize()
var option = AddOption("GOOG");
_optionSymbol = option.Symbol;
- option.SetFilter(-2, +2, 0, 180);
+ option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2).Expiration(0, 180));
}
public override void OnData(Slice slice)
@@ -111,7 +111,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 7;
+ public int AlgorithmHistoryDataPoints => 175;
///
/// Final status of the algorithm
@@ -147,10 +147,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "0"},
{"Total Fees", "$24.70"},
{"Estimated Strategy Capacity", "$6000.00"},
- {"Lowest Capacity Asset", "GOOCV 30AKMELSHQVZA|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 30AKMELSHV6AU|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "208.51%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "80f3cfbffc903339387a788a4d35dad1"}
+ {"OrderListHash", "574530af8e007d4b770b3782bbe31b1b"}
};
}
}
diff --git a/Algorithm.CSharp/LimitOrdersAreFilledAfterHoursForFuturesRegressionAlgorithm.cs b/Algorithm.CSharp/LimitOrdersAreFilledAfterHoursForFuturesRegressionAlgorithm.cs
index fe676af4387e..a6473ce5c98e 100644
--- a/Algorithm.CSharp/LimitOrdersAreFilledAfterHoursForFuturesRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/LimitOrdersAreFilledAfterHoursForFuturesRegressionAlgorithm.cs
@@ -113,7 +113,7 @@ public override void OnOrderEvent(OrderEvent orderEvent)
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 52987;
+ public long DataPoints => 50978;
///
/// Data Points count of the algorithm history
@@ -133,31 +133,31 @@ public override void OnOrderEvent(OrderEvent orderEvent)
{"Total Orders", "2"},
{"Average Win", "0%"},
{"Average Loss", "0%"},
- {"Compounding Annual Return", "120.870%"},
- {"Drawdown", "3.700%"},
+ {"Compounding Annual Return", "-9.298%"},
+ {"Drawdown", "2.500%"},
{"Expectancy", "0"},
{"Start Equity", "100000"},
- {"End Equity", "101091.4"},
- {"Net Profit", "1.091%"},
- {"Sharpe Ratio", "4.261"},
- {"Sortino Ratio", "29.094"},
- {"Probabilistic Sharpe Ratio", "58.720%"},
+ {"End Equity", "99866.4"},
+ {"Net Profit", "-0.134%"},
+ {"Sharpe Ratio", "1.959"},
+ {"Sortino Ratio", "4.863"},
+ {"Probabilistic Sharpe Ratio", "53.257%"},
{"Loss Rate", "0%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
- {"Alpha", "1.134"},
- {"Beta", "1.285"},
- {"Annual Standard Deviation", "0.314"},
- {"Annual Variance", "0.098"},
- {"Information Ratio", "15.222"},
- {"Tracking Error", "0.077"},
- {"Treynor Ratio", "1.04"},
+ {"Alpha", "0.239"},
+ {"Beta", "0.695"},
+ {"Annual Standard Deviation", "0.178"},
+ {"Annual Variance", "0.032"},
+ {"Information Ratio", "2.059"},
+ {"Tracking Error", "0.093"},
+ {"Treynor Ratio", "0.501"},
{"Total Fees", "$4.30"},
- {"Estimated Strategy Capacity", "$39000000.00"},
- {"Lowest Capacity Asset", "ES VMKLFZIH2MTD"},
- {"Portfolio Turnover", "33.59%"},
- {"Drawdown Recovery", "3"},
- {"OrderListHash", "8286cb0dd42649527c2c0032ee00e2bd"}
+ {"Estimated Strategy Capacity", "$25000000.00"},
+ {"Lowest Capacity Asset", "ES VU1EHIDJYLMP"},
+ {"Portfolio Turnover", "33.58%"},
+ {"Drawdown Recovery", "0"},
+ {"OrderListHash", "5a14a3f8b50e3117d87c69d6b11102fc"}
};
}
}
diff --git a/Algorithm.CSharp/LiquidatingMultipleOptionStrategiesRegressionAlgorithm.cs b/Algorithm.CSharp/LiquidatingMultipleOptionStrategiesRegressionAlgorithm.cs
index 0d7f661359d2..fe45a4c7fa5f 100644
--- a/Algorithm.CSharp/LiquidatingMultipleOptionStrategiesRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/LiquidatingMultipleOptionStrategiesRegressionAlgorithm.cs
@@ -50,7 +50,7 @@ public override void Initialize()
SetCash(500000);
var option = AddOption("GOOG");
- option.SetFilter(universe => universe.Strikes(-3, 3).Expiration(0, 180));
+ option.SetFilter(universe => universe.StandardsOnly().Strikes(-3, 3).Expiration(0, 180));
_symbol = option.Symbol;
}
@@ -188,10 +188,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "0"},
{"Total Fees", "$8.00"},
{"Estimated Strategy Capacity", "$13000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZERHAT67A|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "1.31%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "61b9991ec6483ed14639c9839a653b9e"}
+ {"OrderListHash", "7e6fb74d29704118659d2fcc59b6cd78"}
};
}
}
diff --git a/Algorithm.CSharp/LongAndShortButterflyCallStrategiesAlgorithm.cs b/Algorithm.CSharp/LongAndShortButterflyCallStrategiesAlgorithm.cs
index 028b4072465c..87e035d06ca5 100644
--- a/Algorithm.CSharp/LongAndShortButterflyCallStrategiesAlgorithm.cs
+++ b/Algorithm.CSharp/LongAndShortButterflyCallStrategiesAlgorithm.cs
@@ -160,10 +160,10 @@ protected override void LiquidateStrategy()
{"Treynor Ratio", "0"},
{"Total Fees", "$10.40"},
{"Estimated Strategy Capacity", "$7000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZFMEBBB2E|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZFMEBFLDY|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "2.17%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "4026c2d0b0d8de3bd1f375a77d5b5c97"}
+ {"OrderListHash", "819b008b902a1a0013646a12d31f4ae4"}
};
}
}
diff --git a/Algorithm.CSharp/LongAndShortButterflyPutStrategiesAlgorithm.cs b/Algorithm.CSharp/LongAndShortButterflyPutStrategiesAlgorithm.cs
index 0a2a8f0bf6d9..2cf4a57c02d6 100644
--- a/Algorithm.CSharp/LongAndShortButterflyPutStrategiesAlgorithm.cs
+++ b/Algorithm.CSharp/LongAndShortButterflyPutStrategiesAlgorithm.cs
@@ -160,10 +160,10 @@ protected override void LiquidateStrategy()
{"Treynor Ratio", "0"},
{"Total Fees", "$10.40"},
{"Estimated Strategy Capacity", "$4000.00"},
- {"Lowest Capacity Asset", "GOOCV 306CZL2DIL4G6|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 306CZL2DIPERQ|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "2.23%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "5edf17765f812f4b6114c03bb69a3bc2"}
+ {"OrderListHash", "cf836c2b04e698db4f69048870f3fb1c"}
};
}
}
diff --git a/Algorithm.CSharp/LongAndShortCallCalendarSpreadStrategiesAlgorithm.cs b/Algorithm.CSharp/LongAndShortCallCalendarSpreadStrategiesAlgorithm.cs
index 481c9502b6d2..ea79cd66f0b0 100644
--- a/Algorithm.CSharp/LongAndShortCallCalendarSpreadStrategiesAlgorithm.cs
+++ b/Algorithm.CSharp/LongAndShortCallCalendarSpreadStrategiesAlgorithm.cs
@@ -143,10 +143,10 @@ protected override void LiquidateStrategy()
{"Treynor Ratio", "0"},
{"Total Fees", "$5.20"},
{"Estimated Strategy Capacity", "$7000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZEOEHQRYE|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZEOEHV29Y|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "1.85%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "fde9204f63cc0d6676155381fc7537ff"}
+ {"OrderListHash", "ee77a60de004210b9ab977f397c70f73"}
};
}
}
diff --git a/Algorithm.CSharp/LongAndShortPutCalendarSpreadStrategiesAlgorithm.cs b/Algorithm.CSharp/LongAndShortPutCalendarSpreadStrategiesAlgorithm.cs
index 5a25f89add4e..dc8047b22fa4 100644
--- a/Algorithm.CSharp/LongAndShortPutCalendarSpreadStrategiesAlgorithm.cs
+++ b/Algorithm.CSharp/LongAndShortPutCalendarSpreadStrategiesAlgorithm.cs
@@ -143,10 +143,10 @@ protected override void LiquidateStrategy()
{"Treynor Ratio", "0"},
{"Total Fees", "$5.20"},
{"Estimated Strategy Capacity", "$14000.00"},
- {"Lowest Capacity Asset", "GOOCV 306CZK4DP0LC6|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 306CZK4DP4VNQ|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "1.87%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "4c07701fd7a79beca45efc3afebbd693"}
+ {"OrderListHash", "c86c7c9e58f41cbea206196e5717ce4f"}
};
}
}
diff --git a/Algorithm.CSharp/LongAndShortStraddleStrategiesAlgorithm.cs b/Algorithm.CSharp/LongAndShortStraddleStrategiesAlgorithm.cs
index 61a8241ac3be..f657fb788386 100644
--- a/Algorithm.CSharp/LongAndShortStraddleStrategiesAlgorithm.cs
+++ b/Algorithm.CSharp/LongAndShortStraddleStrategiesAlgorithm.cs
@@ -140,10 +140,10 @@ protected override void LiquidateStrategy()
{"Treynor Ratio", "0"},
{"Total Fees", "$5.20"},
{"Estimated Strategy Capacity", "$16000.00"},
- {"Lowest Capacity Asset", "GOOCV WBGM92QHIYO6|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV WBGM92QHN8ZQ|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "4.31%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "cccaf73a927ca18dc8d11634bc80d198"}
+ {"OrderListHash", "c9b2bbdb35e439484e1ae97cfdfa2977"}
};
}
}
diff --git a/Algorithm.CSharp/LongAndShortStrangleStrategiesAlgorithm.cs b/Algorithm.CSharp/LongAndShortStrangleStrategiesAlgorithm.cs
index efd7f4d6c3b5..703a93194a0f 100644
--- a/Algorithm.CSharp/LongAndShortStrangleStrategiesAlgorithm.cs
+++ b/Algorithm.CSharp/LongAndShortStrangleStrategiesAlgorithm.cs
@@ -150,10 +150,10 @@ protected override void LiquidateStrategy()
{"Treynor Ratio", "0"},
{"Total Fees", "$5.20"},
{"Estimated Strategy Capacity", "$15000.00"},
- {"Lowest Capacity Asset", "GOOCV 30AKMELSHQVZA|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 30AKMELSHV6AU|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "4.21%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "c7b4e8981536d76878cf9dd5bd6fc771"}
+ {"OrderListHash", "7037493f637362745f993c1dc940bd05"}
};
}
}
diff --git a/Algorithm.CSharp/MarketOnCloseOrderFillsOnCloseTradeWithTickResolutionAlgorithm.cs b/Algorithm.CSharp/MarketOnCloseOrderFillsOnCloseTradeWithTickResolutionAlgorithm.cs
index e75ca4ace10c..18d1309c5780 100644
--- a/Algorithm.CSharp/MarketOnCloseOrderFillsOnCloseTradeWithTickResolutionAlgorithm.cs
+++ b/Algorithm.CSharp/MarketOnCloseOrderFillsOnCloseTradeWithTickResolutionAlgorithm.cs
@@ -143,7 +143,7 @@ public override void OnEndOfAlgorithm()
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
{"Portfolio Turnover", "0.02%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "dafe02af29d6a320da2e5dad28411559"}
+ {"OrderListHash", "9d53c0501981b8d3aa922bbc45b6e80f"}
};
}
}
diff --git a/Algorithm.CSharp/MarketOnOpenOrderFillsOnOpenTradeWithTickResolutionAlgorithm.cs b/Algorithm.CSharp/MarketOnOpenOrderFillsOnOpenTradeWithTickResolutionAlgorithm.cs
index d0dd0a8679dd..507bd4c794cb 100644
--- a/Algorithm.CSharp/MarketOnOpenOrderFillsOnOpenTradeWithTickResolutionAlgorithm.cs
+++ b/Algorithm.CSharp/MarketOnOpenOrderFillsOnOpenTradeWithTickResolutionAlgorithm.cs
@@ -143,7 +143,7 @@ public override void OnEndOfAlgorithm()
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
{"Portfolio Turnover", "0.02%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "8940204f430a8040b372cc22d80f1399"}
+ {"OrderListHash", "e1d37155b945867337ae64a1807bf0ce"}
};
}
}
diff --git a/Algorithm.CSharp/MarketOrdersAreSupportedOnExtendedHoursForFuturesRegressionAlgorithm.cs b/Algorithm.CSharp/MarketOrdersAreSupportedOnExtendedHoursForFuturesRegressionAlgorithm.cs
index da05ce7ac517..125046779e53 100644
--- a/Algorithm.CSharp/MarketOrdersAreSupportedOnExtendedHoursForFuturesRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/MarketOrdersAreSupportedOnExtendedHoursForFuturesRegressionAlgorithm.cs
@@ -90,7 +90,7 @@ public override void OnOrderEvent(OrderEvent orderEvent)
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 52987;
+ public long DataPoints => 50978;
///
/// Data Points count of the algorithm history
@@ -110,31 +110,31 @@ public override void OnOrderEvent(OrderEvent orderEvent)
{"Total Orders", "2"},
{"Average Win", "0%"},
{"Average Loss", "0%"},
- {"Compounding Annual Return", "113.036%"},
- {"Drawdown", "3.700%"},
+ {"Compounding Annual Return", "-0.626%"},
+ {"Drawdown", "2.400%"},
{"Expectancy", "0"},
{"Start Equity", "100000"},
- {"End Equity", "101041.4"},
- {"Net Profit", "1.041%"},
- {"Sharpe Ratio", "4.262"},
- {"Sortino Ratio", "29.102"},
- {"Probabilistic Sharpe Ratio", "58.720%"},
+ {"End Equity", "99991.4"},
+ {"Net Profit", "-0.009%"},
+ {"Sharpe Ratio", "1.959"},
+ {"Sortino Ratio", "4.862"},
+ {"Probabilistic Sharpe Ratio", "53.257%"},
{"Loss Rate", "0%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
- {"Alpha", "1.135"},
- {"Beta", "1.285"},
- {"Annual Standard Deviation", "0.314"},
- {"Annual Variance", "0.098"},
- {"Information Ratio", "15.206"},
- {"Tracking Error", "0.078"},
- {"Treynor Ratio", "1.04"},
+ {"Alpha", "0.239"},
+ {"Beta", "0.694"},
+ {"Annual Standard Deviation", "0.177"},
+ {"Annual Variance", "0.031"},
+ {"Information Ratio", "2.05"},
+ {"Tracking Error", "0.093"},
+ {"Treynor Ratio", "0.501"},
{"Total Fees", "$4.30"},
- {"Estimated Strategy Capacity", "$12000000.00"},
- {"Lowest Capacity Asset", "ES VMKLFZIH2MTD"},
- {"Portfolio Turnover", "33.61%"},
+ {"Estimated Strategy Capacity", "$15000000.00"},
+ {"Lowest Capacity Asset", "ES VU1EHIDJYLMP"},
+ {"Portfolio Turnover", "33.51%"},
{"Drawdown Recovery", "3"},
- {"OrderListHash", "1a8899e6c1498f63634de38910878619"}
+ {"OrderListHash", "523d76e17b23ee0c94ded9f826cb8c22"}
};
}
}
diff --git a/Algorithm.CSharp/NakedCallStrategyAlgorithm.cs b/Algorithm.CSharp/NakedCallStrategyAlgorithm.cs
index 36f6cb83d2c7..079e92821b3c 100644
--- a/Algorithm.CSharp/NakedCallStrategyAlgorithm.cs
+++ b/Algorithm.CSharp/NakedCallStrategyAlgorithm.cs
@@ -129,10 +129,10 @@ protected override void LiquidateStrategy()
{"Treynor Ratio", "0"},
{"Total Fees", "$2.60"},
{"Estimated Strategy Capacity", "$8000.00"},
- {"Lowest Capacity Asset", "GOOCV WBGM92QHIYO6|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV WBGM92QHN8ZQ|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "2.19%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "56c4d8b527d4a8f8d1cc659f8b2d4fc7"}
+ {"OrderListHash", "6942c6b893f9d77dce3c2f7b5e753718"}
};
}
}
diff --git a/Algorithm.CSharp/NakedPutStrategyAlgorithm.cs b/Algorithm.CSharp/NakedPutStrategyAlgorithm.cs
index 7cacd09e6569..fcf557dd8967 100644
--- a/Algorithm.CSharp/NakedPutStrategyAlgorithm.cs
+++ b/Algorithm.CSharp/NakedPutStrategyAlgorithm.cs
@@ -129,10 +129,10 @@ protected override void LiquidateStrategy()
{"Treynor Ratio", "0"},
{"Total Fees", "$2.60"},
{"Estimated Strategy Capacity", "$10000.00"},
- {"Lowest Capacity Asset", "GOOCV 30AKMEIPOSS1Y|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 30AKMEIPOX2DI|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "2.13%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "be055400ff8650bd9aeabd98e7d89c4e"}
+ {"OrderListHash", "699eda4fdbcfa625cc7cb6c4ccbbd7ba"}
};
}
}
diff --git a/Algorithm.CSharp/NakedShortOptionStrategyOverMarginAlgorithm.cs b/Algorithm.CSharp/NakedShortOptionStrategyOverMarginAlgorithm.cs
index 3cc7943fb001..68aa60f75bf5 100644
--- a/Algorithm.CSharp/NakedShortOptionStrategyOverMarginAlgorithm.cs
+++ b/Algorithm.CSharp/NakedShortOptionStrategyOverMarginAlgorithm.cs
@@ -49,7 +49,7 @@ public override void Initialize()
var option = AddOption("GOOG");
_optionSymbol = option.Symbol;
- option.SetFilter(-2, +2, 0, 180);
+ option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2).Expiration(0, 180));
SetBenchmark("GOOG");
}
@@ -172,10 +172,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "0"},
{"Total Fees", "$9.10"},
{"Estimated Strategy Capacity", "$2600000.00"},
- {"Lowest Capacity Asset", "GOOCV 30AKMEIPOSS1Y|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 30AKMEIPOX2DI|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "7.50%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "70487a4231ef2237ca24642be28652c4"}
+ {"OrderListHash", "67fba235c5efade156e60ed66e4b8031"}
};
}
}
diff --git a/Algorithm.CSharp/NonDynamicOptionsFilterRegressionAlgorithm.cs b/Algorithm.CSharp/NonDynamicOptionsFilterRegressionAlgorithm.cs
index 48d0c1a0ad65..c48a8f0f48c0 100644
--- a/Algorithm.CSharp/NonDynamicOptionsFilterRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/NonDynamicOptionsFilterRegressionAlgorithm.cs
@@ -44,7 +44,7 @@ public override void Initialize()
var option = AddOption(UnderlyingTicker);
_optionSymbol = option.Symbol;
- option.SetFilter(u => u.Strikes(-2, +2).Expiration(0, 180 * 3));
+ option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2).Expiration(0, 180 * 3));
SetBenchmark(equity.Symbol);
}
diff --git a/Algorithm.CSharp/NullBuyingPowerOptionBullCallSpreadAlgorithm.cs b/Algorithm.CSharp/NullBuyingPowerOptionBullCallSpreadAlgorithm.cs
index bbe1f89cd4a3..9d841ec95051 100644
--- a/Algorithm.CSharp/NullBuyingPowerOptionBullCallSpreadAlgorithm.cs
+++ b/Algorithm.CSharp/NullBuyingPowerOptionBullCallSpreadAlgorithm.cs
@@ -47,7 +47,7 @@ public override void Initialize()
var option = AddOption(equity.Symbol);
_optionSymbol = option.Symbol;
- option.SetFilter(-2, +2, 0, 180);
+ option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2).Expiration(0, 180));
}
public override void OnData(Slice slice)
@@ -148,10 +148,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "0"},
{"Total Fees", "$1300.00"},
{"Estimated Strategy Capacity", "$36000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZERHAT67A|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "2888.68%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "ce2d1d95115c73052aa0268491ff2423"}
+ {"OrderListHash", "8a2ee1e491737ecabd775ad5afbe2e4b"}
};
}
}
diff --git a/Algorithm.CSharp/NullMarginComboOrderRegressionAlgorithm.cs b/Algorithm.CSharp/NullMarginComboOrderRegressionAlgorithm.cs
index 18e6771e963b..b2fa12a5b0a8 100644
--- a/Algorithm.CSharp/NullMarginComboOrderRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/NullMarginComboOrderRegressionAlgorithm.cs
@@ -75,7 +75,7 @@ protected override void PlaceTrades(OptionContract optionContract)
{"Lowest Capacity Asset", "GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "7580.62%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "5d8c976a405e1e5d1b19af0d1cdbf05d"}
+ {"OrderListHash", "06de8022dfcb44c5eb0a2199bd7a7232"}
};
}
}
diff --git a/Algorithm.CSharp/NullMarginMultipleOrdersRegressionAlgorithm.cs b/Algorithm.CSharp/NullMarginMultipleOrdersRegressionAlgorithm.cs
index 45c068666bcb..8dba36b6308e 100644
--- a/Algorithm.CSharp/NullMarginMultipleOrdersRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/NullMarginMultipleOrdersRegressionAlgorithm.cs
@@ -45,7 +45,7 @@ public override void Initialize()
var option = AddOption(equity.Symbol);
OptionSymbol = option.Symbol;
- option.SetFilter(u => u.Strikes(-2, +2).Expiration(0, 180));
+ option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2).Expiration(0, 180));
}
protected virtual void OverrideMarginModels()
@@ -75,7 +75,7 @@ public override void OnData(Slice slice)
.ThenBy(x => x.Strike)
.First();
- if(!_placedTrades)
+ if (!_placedTrades)
{
_placedTrades = true;
PlaceTrades(atmContracts);
@@ -100,7 +100,7 @@ protected virtual void AssertState(OrderTicket ticket, int expectedGroupCount, i
{
throw new RegressionTestException($"Unexpected position group count {Portfolio.Positions.Groups.Count} for symbol {ticket.Symbol} and quantity {ticket.Quantity}");
}
- if(Portfolio.TotalMarginUsed != expectedMarginUsed)
+ if (Portfolio.TotalMarginUsed != expectedMarginUsed)
{
throw new RegressionTestException($"Unexpected margin used {expectedMarginUsed}");
}
@@ -163,7 +163,7 @@ protected virtual void AssertState(OrderTicket ticket, int expectedGroupCount, i
{"Lowest Capacity Asset", "GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "7580.62%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "ea13456d0c97785f9f2fc12842831990"}
+ {"OrderListHash", "4b36a135ed647a66c1ef3f1d9439cf02"}
};
}
}
diff --git a/Algorithm.CSharp/NullOptionAssignmentRegressionAlgorithm.cs b/Algorithm.CSharp/NullOptionAssignmentRegressionAlgorithm.cs
index 2e9fff489068..aa24e13b3123 100644
--- a/Algorithm.CSharp/NullOptionAssignmentRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/NullOptionAssignmentRegressionAlgorithm.cs
@@ -72,7 +72,7 @@ public override void Initialize()
{"Lowest Capacity Asset", "GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "26.71%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "2d12d0562e5fc5c45cf8b59398ed59b0"}
+ {"OrderListHash", "5d0637a25841a3eb1344e8564792acb7"}
};
}
}
diff --git a/Algorithm.CSharp/OpenInterestFuturesRegressionAlgorithm.cs b/Algorithm.CSharp/OpenInterestFuturesRegressionAlgorithm.cs
index 17715252bc39..263ccb37a919 100644
--- a/Algorithm.CSharp/OpenInterestFuturesRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OpenInterestFuturesRegressionAlgorithm.cs
@@ -133,10 +133,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$9.88"},
{"Estimated Strategy Capacity", "$0"},
- {"Lowest Capacity Asset", "GC VMRHKN2NLWV1"},
+ {"Lowest Capacity Asset", "GC VOFJUCDY9XNH"},
{"Portfolio Turnover", "1.32%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "cc9ca77de1272050971b5438e757df61"}
+ {"OrderListHash", "4a7e699024771890b97c4ab74365e4b7"}
};
}
}
diff --git a/Algorithm.CSharp/OptionAssignmentRegressionAlgorithm.cs b/Algorithm.CSharp/OptionAssignmentRegressionAlgorithm.cs
index 38b5a2296640..8622e8720b9d 100644
--- a/Algorithm.CSharp/OptionAssignmentRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionAssignmentRegressionAlgorithm.cs
@@ -92,7 +92,7 @@ public override void OnData(Slice slice)
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 4025;
+ public long DataPoints => 4026;
///
/// Data Points count of the algorithm history
@@ -133,10 +133,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "-0.229"},
{"Total Fees", "$16.00"},
{"Estimated Strategy Capacity", "$710000.00"},
- {"Lowest Capacity Asset", "GOOCV 305RBQ20WHPNQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 305RBQ20WLZZA|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "218.80%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "29afd40aab156229739653124c4cab4f"}
+ {"OrderListHash", "590ba58e303f1f60f855f458300d08af"}
};
}
}
diff --git a/Algorithm.CSharp/OptionAssignmentStatisticsRegressionAlgorithm.cs b/Algorithm.CSharp/OptionAssignmentStatisticsRegressionAlgorithm.cs
index c5c7268adec0..42a3c3962f57 100644
--- a/Algorithm.CSharp/OptionAssignmentStatisticsRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionAssignmentStatisticsRegressionAlgorithm.cs
@@ -68,11 +68,6 @@ public override void Initialize()
public override void OnData(Slice slice)
{
- if (_goog.Price == 0 || _googCall600.Price == 0 || _googCall650.Price == 0)
- {
- return;
- }
-
if (!Portfolio.Invested)
{
if (Time < _googCall600Symbol.ID.Date)
@@ -266,7 +261,7 @@ private static bool AreEqual(decimal expected, decimal actual)
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 4358;
+ public long DataPoints => 4359;
///
/// Data Points count of the algorithm history
@@ -310,7 +305,7 @@ private static bool AreEqual(decimal expected, decimal actual)
{"Lowest Capacity Asset", "GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "50.31%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "eaa9f229fb4efb0beaccbbd71881268a"}
+ {"OrderListHash", "65544a2eaccc912e8c81519f5975da1a"}
};
}
}
diff --git a/Algorithm.CSharp/OptionChainApisConsistencyRegressionAlgorithm.cs b/Algorithm.CSharp/OptionChainApisConsistencyRegressionAlgorithm.cs
index c5fa4dd360f6..bb39d036e387 100644
--- a/Algorithm.CSharp/OptionChainApisConsistencyRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionChainApisConsistencyRegressionAlgorithm.cs
@@ -38,10 +38,10 @@ public override void Initialize()
var option = GetOption();
- var optionChainFromAlgorithmApi = OptionChain(option.Symbol).Contracts.Values.Select(x => x.Symbol).ToList();
+ var optionChainFromAlgorithmApi = OptionChain(option.Symbol).Contracts.Keys.ToList();
var exchangeTime = UtcTime.ConvertFromUtc(option.Exchange.TimeZone);
- var optionChainFromProviderApi = OptionChainProvider.GetOptionContractList(option.Symbol, exchangeTime).ToList();
+ var optionChainFromProviderApi = OptionChainProvider.GetOptionContractList(option.Symbol, exchangeTime).Order().ToList();
if (optionChainFromAlgorithmApi.Count == 0)
{
diff --git a/Algorithm.CSharp/OptionChainConsistencyRegressionAlgorithm.cs b/Algorithm.CSharp/OptionChainConsistencyRegressionAlgorithm.cs
index 87b21c29067b..018693e5abe9 100644
--- a/Algorithm.CSharp/OptionChainConsistencyRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionChainConsistencyRegressionAlgorithm.cs
@@ -159,10 +159,10 @@ public override void OnOrderEvent(OrderEvent orderEvent)
{"Treynor Ratio", "0"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$5000.00"},
- {"Lowest Capacity Asset", "GOOCV W6NBKPFL0ACM|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W6NBKPFL4KO6|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "9.93%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "8887ac32d29175b21e40f335437cee61"}
+ {"OrderListHash", "29e41c0e2a316485a2761c4e56189585"}
};
}
}
diff --git a/Algorithm.CSharp/OptionChainFullDataRegressionAlgorithm.cs b/Algorithm.CSharp/OptionChainFullDataRegressionAlgorithm.cs
index 36bb119f487b..9b1bb4dd4262 100644
--- a/Algorithm.CSharp/OptionChainFullDataRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionChainFullDataRegressionAlgorithm.cs
@@ -119,10 +119,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$209.00"},
{"Estimated Strategy Capacity", "$0"},
- {"Lowest Capacity Asset", "GOOCV W6U7PD1F2WYU|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W6U7PD1F77AE|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "85.46%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "a7ab1a9e64fe9ba76ea33a40a78a4e3b"}
+ {"OrderListHash", "8ee1c7a1574ae0ad6f231ad0b7d15310"}
};
}
}
diff --git a/Algorithm.CSharp/OptionChainIncludeWeeklysByDefaultRegressionAlgorithm.cs b/Algorithm.CSharp/OptionChainIncludeWeeklysByDefaultRegressionAlgorithm.cs
new file mode 100644
index 000000000000..e5e83a2d686b
--- /dev/null
+++ b/Algorithm.CSharp/OptionChainIncludeWeeklysByDefaultRegressionAlgorithm.cs
@@ -0,0 +1,143 @@
+/*
+ * 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 QuantConnect.Data;
+using QuantConnect.Data.Market;
+using QuantConnect.Interfaces;
+using QuantConnect.Securities.Option;
+using System.Collections.Generic;
+
+namespace QuantConnect.Algorithm.CSharp
+{
+ ///
+ /// Verifies that weekly option contracts are included when no standard contracts are available.
+ ///
+ public class OptionChainIncludeWeeklysByDefaultRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
+ {
+ private Option _option;
+ private Symbol _optionSymbol;
+ private int _weeklyCount;
+ private int _totalCount;
+
+ ///
+ /// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
+ ///
+ public override void Initialize()
+ {
+ SetStartDate(2015, 12, 24);
+ SetEndDate(2015, 12, 24);
+
+ _option = AddOption("GOOG");
+ _optionSymbol = _option.Symbol;
+
+ _option.SetFilter((optionFilter) =>
+ {
+ return optionFilter.Strikes(-8, +8).Expiration(0, 0);
+ });
+ }
+
+ ///
+ /// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
+ ///
+ /// Slice object keyed by symbol containing the stock data
+ public override void OnData(Slice slice)
+ {
+ OptionChain chain;
+ if (slice.OptionChains.TryGetValue(_optionSymbol, out chain))
+ {
+ _totalCount += chain.Contracts.Count;
+ foreach (var contract in chain.Contracts.Values)
+ {
+ if (!OptionSymbol.IsStandard(contract.Symbol))
+ {
+ _weeklyCount++;
+ }
+ }
+ }
+ }
+
+ public override void OnEndOfAlgorithm()
+ {
+ if (_weeklyCount == 0)
+ {
+ throw new RegressionTestException("No weekly contracts found");
+ }
+ if (_totalCount != _weeklyCount)
+ {
+ throw new RegressionTestException("When no standard option expirations are available, the option chain must fall back to weekly contracts only");
+ }
+ }
+
+ ///
+ /// 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, Language.Python };
+
+ ///
+ /// Data Points count of all timeslices of algorithm
+ ///
+ public long DataPoints => 22702;
+
+ ///
+ /// 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", "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", "0"},
+ {"Tracking Error", "0"},
+ {"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/OptionChainProviderAlgorithm.cs b/Algorithm.CSharp/OptionChainProviderAlgorithm.cs
index ad423e35029d..1d09e6dbc715 100644
--- a/Algorithm.CSharp/OptionChainProviderAlgorithm.cs
+++ b/Algorithm.CSharp/OptionChainProviderAlgorithm.cs
@@ -136,10 +136,10 @@ where symbol.ID.StrikePrice - underlyingPrice > 0
{"Treynor Ratio", "0"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$6300000.00"},
- {"Lowest Capacity Asset", "GOOCV W723A0UB7HTY|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W723A0UBBS5I|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "76.04%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "d7290944d7fee84f232b47d658010730"}
+ {"OrderListHash", "20963045be4abe2ce837a0261329462d"}
};
}
}
diff --git a/Algorithm.CSharp/OptionChainSubscriptionRemovalRegressionAlgorithm.cs b/Algorithm.CSharp/OptionChainSubscriptionRemovalRegressionAlgorithm.cs
index 2539a3a60cd4..3751c49da7fc 100644
--- a/Algorithm.CSharp/OptionChainSubscriptionRemovalRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionChainSubscriptionRemovalRegressionAlgorithm.cs
@@ -96,7 +96,7 @@ public TestOptionUniverseSelectionModel(Func> opti
protected override OptionFilterUniverse Filter(OptionFilterUniverse filter)
{
- return filter.BackMonth().Contracts(contracts => contracts.Take(15));
+ return filter.StandardsOnly().BackMonth().Contracts(contracts => contracts.Take(15));
}
}
@@ -113,7 +113,7 @@ protected override OptionFilterUniverse Filter(OptionFilterUniverse filter)
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 2155693;
+ public long DataPoints => 2155694;
///
/// Data Points count of the algorithm history
diff --git a/Algorithm.CSharp/OptionChainedAndUniverseSelectionRegressionAlgorithm.cs b/Algorithm.CSharp/OptionChainedAndUniverseSelectionRegressionAlgorithm.cs
index 76fd1c30a248..bca3c938ae18 100644
--- a/Algorithm.CSharp/OptionChainedAndUniverseSelectionRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionChainedAndUniverseSelectionRegressionAlgorithm.cs
@@ -36,7 +36,9 @@ public override void Initialize()
SetStartDate(2014, 06, 05);
SetEndDate(2014, 06, 09);
- _aaplOption = AddOption("AAPL").Symbol;
+ var option = AddOption("AAPL");
+ option.SetFilter(u => u.StandardsOnly().Strikes(-1, 1).Expiration(0, 35));
+ _aaplOption = option.Symbol;
AddUniverseSelection(new DailyUniverseSelectionModel("MyCustomSelectionModel", time => new[] { "AAPL" }, this));
}
diff --git a/Algorithm.CSharp/OptionChainedUniverseSelectionModelRegressionAlgorithm.cs b/Algorithm.CSharp/OptionChainedUniverseSelectionModelRegressionAlgorithm.cs
index 73cf8d03f026..77178fc1190d 100644
--- a/Algorithm.CSharp/OptionChainedUniverseSelectionModelRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionChainedUniverseSelectionModelRegressionAlgorithm.cs
@@ -28,7 +28,7 @@ namespace QuantConnect.Algorithm.CSharp
///
/// Regression algorithm to test the OptionChainedUniverseSelectionModel class
///
- public class OptionChainedUniverseSelectionModelRegressionAlgorithm: QCAlgorithm, IRegressionAlgorithmDefinition
+ public class OptionChainedUniverseSelectionModelRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
public override void Initialize()
{
@@ -39,7 +39,7 @@ public override void Initialize()
var universe = AddUniverse("my-minute-universe-name", time => new List { "AAPL", "TWX" });
- AddUniverseSelection(new OptionChainedUniverseSelectionModel(universe, u => u.Strikes(-2, +2)
+ AddUniverseSelection(new OptionChainedUniverseSelectionModel(universe, u => u.StandardsOnly().Strikes(-2, +2)
// Expiration method accepts TimeSpan objects or integer for days.
// The following statements yield the same filtering criteria
.Expiration(0, 180)));
@@ -124,10 +124,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$4.00"},
{"Estimated Strategy Capacity", "$110000.00"},
- {"Lowest Capacity Asset", "AAPL 2ZTXYLO9EQPZA|AAPL R735QTJ8XC9X"},
+ {"Lowest Capacity Asset", "AAPL 2ZTXYLO9EV0AU|AAPL R735QTJ8XC9X"},
{"Portfolio Turnover", "8.85%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "a542a51c6e634f2ddd9a97ce208d5a67"}
+ {"OrderListHash", "32f3cebb622264a2d6fd84c552ff4d0e"}
};
}
}
diff --git a/Algorithm.CSharp/OptionChainsMultipleFullDataRegressionAlgorithm.cs b/Algorithm.CSharp/OptionChainsMultipleFullDataRegressionAlgorithm.cs
index 7745ec39ea70..f1e180fe6ccd 100644
--- a/Algorithm.CSharp/OptionChainsMultipleFullDataRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionChainsMultipleFullDataRegressionAlgorithm.cs
@@ -134,10 +134,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$209.00"},
{"Estimated Strategy Capacity", "$0"},
- {"Lowest Capacity Asset", "GOOCV W6U7PD1F2WYU|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W6U7PD1F77AE|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "85.46%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "a7ab1a9e64fe9ba76ea33a40a78a4e3b"}
+ {"OrderListHash", "8ee1c7a1574ae0ad6f231ad0b7d15310"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityBaseStrategyRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityBaseStrategyRegressionAlgorithm.cs
index 279a5a315077..c118b97bb3fb 100644
--- a/Algorithm.CSharp/OptionEquityBaseStrategyRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityBaseStrategyRegressionAlgorithm.cs
@@ -43,7 +43,7 @@ public override void Initialize()
_optionSymbol = option.Symbol;
// set our strike/expiry filter for this option chain
- option.SetFilter(u => u.Strikes(-2, +2)
+ option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2)
// Expiration method accepts TimeSpan objects or integer for days.
// The following statements yield the same filtering criteria
.Expiration(0, 180));
@@ -80,12 +80,12 @@ protected decimal GetPriceSpreadDifference(params Symbol[] symbols)
{
if (security.AskPrice != 0)
{
- spread = security.Price - security.AskPrice;
+ spread = security.Price - security.Holdings.AveragePrice;
}
}
- else if(security.BidPrice != 0)
+ else if (security.BidPrice != 0)
{
- spread = security.BidPrice - security.Price;
+ spread = security.Holdings.AveragePrice - security.Price;
}
spreadPaid += spread * actualQuantity * security.SymbolProperties.ContractMultiplier;
}
diff --git a/Algorithm.CSharp/OptionEquityBearCallLadderRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityBearCallLadderRegressionAlgorithm.cs
index 8d73f349ce29..ce26459476ba 100644
--- a/Algorithm.CSharp/OptionEquityBearCallLadderRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityBearCallLadderRegressionAlgorithm.cs
@@ -118,10 +118,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$9.75"},
{"Estimated Strategy Capacity", "$47000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZERHAT67A|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "11.48%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "2d7e030df7ade6d6dcc1c715a329ad32"}
+ {"OrderListHash", "a573795b3fb76288c1e8b71b1f2bc928"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityBearCallSpreadRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityBearCallSpreadRegressionAlgorithm.cs
index 97629fbde1ab..1b1997fa47cb 100644
--- a/Algorithm.CSharp/OptionEquityBearCallSpreadRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityBearCallSpreadRegressionAlgorithm.cs
@@ -120,10 +120,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$6.50"},
{"Estimated Strategy Capacity", "$5400000.00"},
- {"Lowest Capacity Asset", "GOOCV WBGM95TAH2LI|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV WBGM95TALCX2|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "28.44%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "e9104f749ad7055346b26e6db3bdb437"}
+ {"OrderListHash", "d5354d8376960b0b11a80bc1a164a6a3"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityBearCallSpreadSetHoldingsRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityBearCallSpreadSetHoldingsRegressionAlgorithm.cs
index 5f9d628fb248..4d3c8b9a1b4d 100644
--- a/Algorithm.CSharp/OptionEquityBearCallSpreadSetHoldingsRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityBearCallSpreadSetHoldingsRegressionAlgorithm.cs
@@ -119,10 +119,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$7.15"},
{"Estimated Strategy Capacity", "$45000000.00"},
- {"Lowest Capacity Asset", "GOOCV WBGM95TAH2LI|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV WBGM95TALCX2|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "6.17%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "8f1288896dafb2856b6045f8930e86a6"}
+ {"OrderListHash", "735ec0801dd3dcf9e03eaf3b67931910"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityBearPutLadderRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityBearPutLadderRegressionAlgorithm.cs
index 194d9edd3389..3a55a35c5abb 100644
--- a/Algorithm.CSharp/OptionEquityBearPutLadderRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityBearPutLadderRegressionAlgorithm.cs
@@ -121,10 +121,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$9.75"},
{"Estimated Strategy Capacity", "$1100000.00"},
- {"Lowest Capacity Asset", "GOOCV 306CZL2DIL4G6|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 306CZL2DIPERQ|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "9.45%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "64e3480ee2ece70a3bb24bef3e7ecdd6"}
+ {"OrderListHash", "344a4a84239e83eda686ea21d086b6fd"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityBearPutSpreadRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityBearPutSpreadRegressionAlgorithm.cs
index b594fc49dca4..1f0ccfac057c 100644
--- a/Algorithm.CSharp/OptionEquityBearPutSpreadRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityBearPutSpreadRegressionAlgorithm.cs
@@ -117,10 +117,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$13.00"},
{"Estimated Strategy Capacity", "$1300000.00"},
- {"Lowest Capacity Asset", "GOOCV 306CZK7GHYP9I|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 306CZK7GI2ZL2|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "13.43%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "fa96a26ab949ba2e053c2fa78930ad70"}
+ {"OrderListHash", "0d10d7319b27523377bb53bbd9702552"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityBoxSpreadRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityBoxSpreadRegressionAlgorithm.cs
index e596dedfd197..97aac6aead0b 100644
--- a/Algorithm.CSharp/OptionEquityBoxSpreadRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityBoxSpreadRegressionAlgorithm.cs
@@ -129,10 +129,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$26.00"},
{"Estimated Strategy Capacity", "$64000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZERHAT67A|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "27.98%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "27e4456cb375fae2a15697c803bc0779"}
+ {"OrderListHash", "153196ec52843cf95d979e14d18b98b5"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityBullCallLadderRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityBullCallLadderRegressionAlgorithm.cs
index e527d57f5742..4fa17dfccb4e 100644
--- a/Algorithm.CSharp/OptionEquityBullCallLadderRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityBullCallLadderRegressionAlgorithm.cs
@@ -121,10 +121,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$9.75"},
{"Estimated Strategy Capacity", "$51000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZERHAT67A|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "11.09%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "87d10f2406a4ce6b9d7685bea26d3daf"}
+ {"OrderListHash", "9412b7091b1e677c662a6bd8acc688a7"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityBullCallSpreadRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityBullCallSpreadRegressionAlgorithm.cs
index 823d42c2264f..8d91244cb552 100644
--- a/Algorithm.CSharp/OptionEquityBullCallSpreadRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityBullCallSpreadRegressionAlgorithm.cs
@@ -116,10 +116,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$4.50"},
{"Estimated Strategy Capacity", "$5400000.00"},
- {"Lowest Capacity Asset", "GOOCV WBGM95TAH2LI|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV WBGM95TALCX2|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "28.20%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "a67da2b19b248ab78686660793ddff73"}
+ {"OrderListHash", "8e7710ac4b8287b4746beddbc5ce9611"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityBullPutLadderRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityBullPutLadderRegressionAlgorithm.cs
index cde8de55751e..e72818ab1b70 100644
--- a/Algorithm.CSharp/OptionEquityBullPutLadderRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityBullPutLadderRegressionAlgorithm.cs
@@ -118,10 +118,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$9.75"},
{"Estimated Strategy Capacity", "$1400000.00"},
- {"Lowest Capacity Asset", "GOOCV 306CZL2DIL4G6|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 306CZL2DIPERQ|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "9.76%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "7e626752cd561e225a1990b19b220177"}
+ {"OrderListHash", "c94aea4f3f3af337890d430a47a078e2"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityBullPutSpreadRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityBullPutSpreadRegressionAlgorithm.cs
index 4f0346b6a9ae..5b47e516b19f 100644
--- a/Algorithm.CSharp/OptionEquityBullPutSpreadRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityBullPutSpreadRegressionAlgorithm.cs
@@ -115,10 +115,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$13.00"},
{"Estimated Strategy Capacity", "$2300000.00"},
- {"Lowest Capacity Asset", "GOOCV 306CZK7GHYP9I|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 306CZK7GI2ZL2|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "13.47%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "ee051f3093b67c6f921eaa0f517b2880"}
+ {"OrderListHash", "674e63d3d499cc9b6c3be48c92786536"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityCallBackspreadRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityCallBackspreadRegressionAlgorithm.cs
index 9085b8ac5b92..35537a699cb3 100644
--- a/Algorithm.CSharp/OptionEquityCallBackspreadRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityCallBackspreadRegressionAlgorithm.cs
@@ -120,10 +120,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$9.75"},
{"Estimated Strategy Capacity", "$47000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZERHAT67A|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "11.81%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "6ece6c59826ea66fa7b0a1094a0021c7"}
+ {"OrderListHash", "d6c330a7840e7294bfa1bc6572d418bd"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityCallButterflyRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityCallButterflyRegressionAlgorithm.cs
index 71114bfb0075..9dbaa7e10ea5 100644
--- a/Algorithm.CSharp/OptionEquityCallButterflyRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityCallButterflyRegressionAlgorithm.cs
@@ -120,10 +120,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$26.00"},
{"Estimated Strategy Capacity", "$69000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZERHAT67A|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "30.35%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "6d90cdf33bc1dd6e8d190021898a4e66"}
+ {"OrderListHash", "1f9515dab3cf62b5e1d9026a2d27a994"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityCallCalendarSpreadRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityCallCalendarSpreadRegressionAlgorithm.cs
index 0f54f7172aea..3743ae349aa3 100644
--- a/Algorithm.CSharp/OptionEquityCallCalendarSpreadRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityCallCalendarSpreadRegressionAlgorithm.cs
@@ -117,10 +117,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$13.00"},
{"Estimated Strategy Capacity", "$23000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZERHAT67A|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "26.19%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "4b1bd9b5d8b0dba8ddaceeb1dfbcbbc9"}
+ {"OrderListHash", "2c84b684c855e060a2dced86497181e0"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityConversionRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityConversionRegressionAlgorithm.cs
index d1e3291ec5e8..f33e0adc6c9c 100644
--- a/Algorithm.CSharp/OptionEquityConversionRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityConversionRegressionAlgorithm.cs
@@ -119,10 +119,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$3.00"},
{"Estimated Strategy Capacity", "$1600000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZFMML01JA|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZFMML4BUU|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "38.88%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "8d8b71fdb1faafde96e301b4b2f9ca7d"}
+ {"OrderListHash", "af86d222380d975e533a88b92b16f280"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityCoveredCallRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityCoveredCallRegressionAlgorithm.cs
index 0033db4720fb..6cafcc12dba9 100644
--- a/Algorithm.CSharp/OptionEquityCoveredCallRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityCoveredCallRegressionAlgorithm.cs
@@ -121,7 +121,7 @@ public override void OnData(Slice slice)
{"Lowest Capacity Asset", "GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "201.44%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "0eee5332f35455eb689a4ef2a27f11fc"}
+ {"OrderListHash", "7bbdaa6bb6a8e92177dbab76992cfea6"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityCoveredPutRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityCoveredPutRegressionAlgorithm.cs
index 301f6a87c274..f600b73bd8e0 100644
--- a/Algorithm.CSharp/OptionEquityCoveredPutRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityCoveredPutRegressionAlgorithm.cs
@@ -122,7 +122,7 @@ public override void OnData(Slice slice)
{"Lowest Capacity Asset", "GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "399.81%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "326721b5b46d1094a5a758c60ba67da0"}
+ {"OrderListHash", "89db7ece35155c62319cbbb810d9a58e"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityIronButterflyRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityIronButterflyRegressionAlgorithm.cs
index 11c0d0ae5b52..b14a42a65e88 100644
--- a/Algorithm.CSharp/OptionEquityIronButterflyRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityIronButterflyRegressionAlgorithm.cs
@@ -127,10 +127,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$26.00"},
{"Estimated Strategy Capacity", "$500000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZFMML01JA|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZFMML4BUU|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "26.45%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "b92ac4977a039360c4b09232ebe9e60f"}
+ {"OrderListHash", "cbf6f38a1ad909fa68c926edaae45f7a"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityIronCondorRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityIronCondorRegressionAlgorithm.cs
index 100d0a64d9f2..bbe4b329ea14 100644
--- a/Algorithm.CSharp/OptionEquityIronCondorRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityIronCondorRegressionAlgorithm.cs
@@ -129,10 +129,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$26.00"},
{"Estimated Strategy Capacity", "$480000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZFMML01JA|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZFMML4BUU|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "25.26%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "ec76ffecec334bc53867752638aee2fa"}
+ {"OrderListHash", "21935ddaaa9549064bbeeca2cd7ba4ac"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityJellyRollRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityJellyRollRegressionAlgorithm.cs
index d011b30a2e78..cf9bf7b9d972 100644
--- a/Algorithm.CSharp/OptionEquityJellyRollRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityJellyRollRegressionAlgorithm.cs
@@ -125,10 +125,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$4.00"},
{"Estimated Strategy Capacity", "$180000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZERHAT67A|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "4.70%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "34f1fe90151a1fc5dff43cd7b1205861"}
+ {"OrderListHash", "b3857d494d146a638a8e70d313d0e724"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityProtectiveCollarRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityProtectiveCollarRegressionAlgorithm.cs
index 4d5553872bef..a1168c89cc09 100644
--- a/Algorithm.CSharp/OptionEquityProtectiveCollarRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityProtectiveCollarRegressionAlgorithm.cs
@@ -120,10 +120,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$3.00"},
{"Estimated Strategy Capacity", "$1600000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZFMML01JA|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZFMML4BUU|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "38.71%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "74791244fa3c7fbefd47dd99c3cd6fa7"}
+ {"OrderListHash", "531dca5eb401dc71132dbdfeec71a4f2"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityPutBackspreadRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityPutBackspreadRegressionAlgorithm.cs
index f500e5429b51..bf74aea0eef1 100644
--- a/Algorithm.CSharp/OptionEquityPutBackspreadRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityPutBackspreadRegressionAlgorithm.cs
@@ -120,10 +120,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$9.75"},
{"Estimated Strategy Capacity", "$1100000.00"},
- {"Lowest Capacity Asset", "GOOCV 306CZL2DIL4G6|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 306CZL2DIPERQ|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "9.15%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "1a51f04db9201f960dc04668b7f5d41d"}
+ {"OrderListHash", "7da2977580a65c43f696a3e013fb8035"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityPutButterflyRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityPutButterflyRegressionAlgorithm.cs
index 948bc4f8961c..5ccba48e7d0d 100644
--- a/Algorithm.CSharp/OptionEquityPutButterflyRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityPutButterflyRegressionAlgorithm.cs
@@ -119,10 +119,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$26.00"},
{"Estimated Strategy Capacity", "$280000.00"},
- {"Lowest Capacity Asset", "GOOCV 306CZL2DIL4G6|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 306CZL2DIPERQ|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "25.77%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "90ff39e71c0e1dea734cd5e7e45f50d4"}
+ {"OrderListHash", "e4d100d6e96ad81660b800f09267a623"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityPutCalendarSpreadRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityPutCalendarSpreadRegressionAlgorithm.cs
index fcd5e71512c0..e73dd6799436 100644
--- a/Algorithm.CSharp/OptionEquityPutCalendarSpreadRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityPutCalendarSpreadRegressionAlgorithm.cs
@@ -116,10 +116,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$13.00"},
{"Estimated Strategy Capacity", "$1300000.00"},
- {"Lowest Capacity Asset", "GOOCV 306CZK7GHYP9I|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 306CZK7GI2ZL2|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "21.14%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "9d0596275684d9baa53937a13d71800e"}
+ {"OrderListHash", "250cf48cc95b03dd9db84ab9ba18a0c4"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityReverseConversionRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityReverseConversionRegressionAlgorithm.cs
index bae67d2cb5de..f52a653c3953 100644
--- a/Algorithm.CSharp/OptionEquityReverseConversionRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityReverseConversionRegressionAlgorithm.cs
@@ -119,10 +119,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$3.00"},
{"Estimated Strategy Capacity", "$7400000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZFMML01JA|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZFMML4BUU|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "38.84%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "722e8214812becc745646ff31fcbce1b"}
+ {"OrderListHash", "5e0bf1da18d2ef159f3771de4bdcc4b9"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityShortBoxSpreadRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityShortBoxSpreadRegressionAlgorithm.cs
index 8980ecb50336..d85b18e89181 100644
--- a/Algorithm.CSharp/OptionEquityShortBoxSpreadRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityShortBoxSpreadRegressionAlgorithm.cs
@@ -136,10 +136,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$26.00"},
{"Estimated Strategy Capacity", "$23000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZERHAT67A|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "28.04%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "f91f438caebb667dda197418168eadd3"}
+ {"OrderListHash", "4f1e402bd285c0ac07a5611fe4776c5f"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityShortButterflyCallRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityShortButterflyCallRegressionAlgorithm.cs
index 04695ccae7c4..8022893810c0 100644
--- a/Algorithm.CSharp/OptionEquityShortButterflyCallRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityShortButterflyCallRegressionAlgorithm.cs
@@ -120,10 +120,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$26.00"},
{"Estimated Strategy Capacity", "$23000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZERHAT67A|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "30.26%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "6588b52d6dbf36c1996fb27ca734a219"}
+ {"OrderListHash", "3e3d9bdac468c34733ae06ddbc4db4d8"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityShortButterflyPutRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityShortButterflyPutRegressionAlgorithm.cs
index 9bd0c59d32ff..607c67588656 100644
--- a/Algorithm.CSharp/OptionEquityShortButterflyPutRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityShortButterflyPutRegressionAlgorithm.cs
@@ -118,10 +118,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$26.00"},
{"Estimated Strategy Capacity", "$890000.00"},
- {"Lowest Capacity Asset", "GOOCV 306CZL2DIL4G6|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 306CZL2DIPERQ|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "25.69%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "96609f0e05a71aea39fd31d90b7273d1"}
+ {"OrderListHash", "9e1b1c3724e5981b74cb03a5c7064914"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityShortCallBackspreadRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityShortCallBackspreadRegressionAlgorithm.cs
index ac5c262e3245..0f7e330e9e44 100644
--- a/Algorithm.CSharp/OptionEquityShortCallBackspreadRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityShortCallBackspreadRegressionAlgorithm.cs
@@ -122,10 +122,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$9.75"},
{"Estimated Strategy Capacity", "$53000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZERHAT67A|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "11.48%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "357f13ed9e71c4dd8bb8e51e339ba7c5"}
+ {"OrderListHash", "8174f45d8e7ca380e7e064cecaf3124d"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityShortIronButterflyRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityShortIronButterflyRegressionAlgorithm.cs
index e538411db097..fd4d10a6ac43 100644
--- a/Algorithm.CSharp/OptionEquityShortIronButterflyRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityShortIronButterflyRegressionAlgorithm.cs
@@ -127,10 +127,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$26.00"},
{"Estimated Strategy Capacity", "$150000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZFMML01JA|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZFMML4BUU|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "26.63%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "2e8aabda630eb75675b202456d2b085a"}
+ {"OrderListHash", "782c4d80f0d098b0a6dccfe54aa74e23"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityShortIronCondorRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityShortIronCondorRegressionAlgorithm.cs
index 110bf8d5b249..ab20e24b35c6 100644
--- a/Algorithm.CSharp/OptionEquityShortIronCondorRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityShortIronCondorRegressionAlgorithm.cs
@@ -124,10 +124,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$26.00"},
{"Estimated Strategy Capacity", "$150000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZFMML01JA|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZFMML4BUU|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "25.35%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "15edd05d23c67c5902994eeeaf0855c7"}
+ {"OrderListHash", "35e7dd1e08bd0b9f4645740b72851d1f"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityShortJellyRollRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityShortJellyRollRegressionAlgorithm.cs
index af8ad0289d45..f5c2f779c078 100644
--- a/Algorithm.CSharp/OptionEquityShortJellyRollRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityShortJellyRollRegressionAlgorithm.cs
@@ -125,10 +125,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$4.00"},
{"Estimated Strategy Capacity", "$110000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZERHAT67A|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "4.70%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "e2eab12be821aad91d9760a50ef9eab9"}
+ {"OrderListHash", "858390f60e75ee2a501d9570ad37a925"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityShortPutBackspreadRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityShortPutBackspreadRegressionAlgorithm.cs
index d074cb559894..5b027dfa6dbe 100644
--- a/Algorithm.CSharp/OptionEquityShortPutBackspreadRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityShortPutBackspreadRegressionAlgorithm.cs
@@ -122,10 +122,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$9.75"},
{"Estimated Strategy Capacity", "$1200000.00"},
- {"Lowest Capacity Asset", "GOOCV 306CZL2DIL4G6|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 306CZL2DIPERQ|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "8.84%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "7294da06231632975e97c57721d26442"}
+ {"OrderListHash", "eeef2acb2fcf1b166d8884fcf8b49bbd"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityStraddleRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityStraddleRegressionAlgorithm.cs
index 0ea9ef9f38b8..553cf76bf190 100644
--- a/Algorithm.CSharp/OptionEquityStraddleRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityStraddleRegressionAlgorithm.cs
@@ -116,10 +116,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$13.00"},
{"Estimated Strategy Capacity", "$270000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZFMML01JA|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZFMML4BUU|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "14.41%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "15b312a11b54cf67489d550260c68f5c"}
+ {"OrderListHash", "b70cd0519217e6970f4aaaa04331ca68"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityStrangleRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityStrangleRegressionAlgorithm.cs
index 4250c3925d6c..13a5b2002f9f 100644
--- a/Algorithm.CSharp/OptionEquityStrangleRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityStrangleRegressionAlgorithm.cs
@@ -116,10 +116,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$13.00"},
{"Estimated Strategy Capacity", "$250000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZFMML01JA|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZFMML4BUU|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "13.14%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "14a2226f740e34fb9c06e5c6ace85ceb"}
+ {"OrderListHash", "a8bc714c098862047c37ce9389e252a5"}
};
}
}
diff --git a/Algorithm.CSharp/OptionEquityStrategyMatcherRegressionAlgorithm.cs b/Algorithm.CSharp/OptionEquityStrategyMatcherRegressionAlgorithm.cs
index 1a5237dc79b1..b727b16dea5c 100644
--- a/Algorithm.CSharp/OptionEquityStrategyMatcherRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionEquityStrategyMatcherRegressionAlgorithm.cs
@@ -153,10 +153,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$36.95"},
{"Estimated Strategy Capacity", "$0"},
- {"Lowest Capacity Asset", "GOOCV W78ZFMEBBB2E|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZFMEBFLDY|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "274.86%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "003871a1f5e8ed7352d41c4b66fe8944"}
+ {"OrderListHash", "6d0e54c4897844ae98e478045bbd1569"}
};
}
}
diff --git a/Algorithm.CSharp/OptionExerciseAssignRegressionAlgorithm.cs b/Algorithm.CSharp/OptionExerciseAssignRegressionAlgorithm.cs
index 631e31615f9e..6fe8d4fc6bd6 100644
--- a/Algorithm.CSharp/OptionExerciseAssignRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionExerciseAssignRegressionAlgorithm.cs
@@ -163,7 +163,7 @@ public override void OnAssignmentOrderEvent(OrderEvent assignmentEvent)
{"Lowest Capacity Asset", "GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "30.10%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "c32a840b8e572bce151e319354df0723"}
+ {"OrderListHash", "b7830811367ced9052c1623875787637"}
};
}
}
diff --git a/Algorithm.CSharp/OptionExerciseOnExpiryAndNonTradableDateRegressionAlgorithm.cs b/Algorithm.CSharp/OptionExerciseOnExpiryAndNonTradableDateRegressionAlgorithm.cs
index 0e0a8748dba4..d4867599a759 100644
--- a/Algorithm.CSharp/OptionExerciseOnExpiryAndNonTradableDateRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionExerciseOnExpiryAndNonTradableDateRegressionAlgorithm.cs
@@ -112,7 +112,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public virtual long DataPoints => 16638;
+ public virtual long DataPoints => 16640;
///
/// Data Points count of the algorithm history
@@ -153,10 +153,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "0"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$8000.00"},
- {"Lowest Capacity Asset", "SPXW Y9T7LPL1X0TQ|SPX 31"},
+ {"Lowest Capacity Asset", "SPXW Y9T7LPL21B5A|SPX 31"},
{"Portfolio Turnover", "0.02%"},
{"Drawdown Recovery", "4"},
- {"OrderListHash", "764432f8c2753cb2d5120a98997da47a"}
+ {"OrderListHash", "a1f4c8031a753d2b73655adf94f9889b"}
};
}
}
diff --git a/Algorithm.CSharp/OptionExerciseRegressionAlgorithm.cs b/Algorithm.CSharp/OptionExerciseRegressionAlgorithm.cs
index 9abd4ea9b605..dc4b6bf6460d 100644
--- a/Algorithm.CSharp/OptionExerciseRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionExerciseRegressionAlgorithm.cs
@@ -154,10 +154,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "0"},
{"Total Fees", "$23.00"},
{"Estimated Strategy Capacity", "$420000.00"},
- {"Lowest Capacity Asset", "AAPL 2ZQA0P58YFYIU|AAPL R735QTJ8XC9X"},
+ {"Lowest Capacity Asset", "AAPL 2ZQA0P58YK8UE|AAPL R735QTJ8XC9X"},
{"Portfolio Turnover", "66.12%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "046413f5ee0d4c200e5a98d823ae5a61"}
+ {"OrderListHash", "8e667d067b15819e8626d2157ce7b0b5"}
};
}
}
diff --git a/Algorithm.CSharp/OptionNoTimeInUniverseRegressionAlgorithm.cs b/Algorithm.CSharp/OptionNoTimeInUniverseRegressionAlgorithm.cs
index 2bd1976119d9..a4bdc47104d0 100644
--- a/Algorithm.CSharp/OptionNoTimeInUniverseRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionNoTimeInUniverseRegressionAlgorithm.cs
@@ -42,7 +42,7 @@ public override void Initialize()
_optionSymbol = option.Symbol;
// set our strike/expiry filter for this option chain
- option.SetFilter(u => u.Strikes(-1, +1)
+ option.SetFilter(u => u.StandardsOnly().Strikes(-1, +1)
// Expiration method accepts TimeSpan objects or integer for days.
// The following statements yield the same filtering criteria
.Expiration(0, 60));
diff --git a/Algorithm.CSharp/OptionOTMExpiryOrderHasZeroPriceRegressionAlgorithm.cs b/Algorithm.CSharp/OptionOTMExpiryOrderHasZeroPriceRegressionAlgorithm.cs
index 51af45f28fed..4a0c6a701dfb 100644
--- a/Algorithm.CSharp/OptionOTMExpiryOrderHasZeroPriceRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionOTMExpiryOrderHasZeroPriceRegressionAlgorithm.cs
@@ -160,7 +160,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 212196;
+ public long DataPoints => 212198;
///
/// Data Points count of the algorithm history
@@ -201,10 +201,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "-23.065"},
{"Total Fees", "$1.42"},
{"Estimated Strategy Capacity", "$180000000.00"},
- {"Lowest Capacity Asset", "ES XFH59UPHGV9G|ES XFH59UK0MYO1"},
+ {"Lowest Capacity Asset", "ES XFH59UPHL5L0|ES XFH59UK0MYO1"},
{"Portfolio Turnover", "0.02%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "1d3c36cec32b24e8911d87d7b9730192"}
+ {"OrderListHash", "d84cd529c8535b576d63c0f9c29635c3"}
};
}
}
diff --git a/Algorithm.CSharp/OptionOpenInterestRegressionAlgorithm.cs b/Algorithm.CSharp/OptionOpenInterestRegressionAlgorithm.cs
index 1a17a8975694..15e8a8d5a63f 100644
--- a/Algorithm.CSharp/OptionOpenInterestRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionOpenInterestRegressionAlgorithm.cs
@@ -164,10 +164,10 @@ public override void OnOrderEvent(OrderEvent orderEvent)
{"Treynor Ratio", "0"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$0"},
- {"Lowest Capacity Asset", "AOL W78ZERDZK1QE|AOL R735QTJ8XC9X"},
+ {"Lowest Capacity Asset", "AOL W78ZERDZOC1Y|AOL R735QTJ8XC9X"},
{"Portfolio Turnover", "0.07%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "58c3e82532109b692429e1eb062296b5"}
+ {"OrderListHash", "020bab5fcb635e1378f404364e9495a2"}
};
}
}
diff --git a/Algorithm.CSharp/OptionOrdersOnSplitRegressionAlgorithm.cs b/Algorithm.CSharp/OptionOrdersOnSplitRegressionAlgorithm.cs
index b0e5b6f31dcd..7f09fba8d76b 100644
--- a/Algorithm.CSharp/OptionOrdersOnSplitRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionOrdersOnSplitRegressionAlgorithm.cs
@@ -42,7 +42,7 @@ public override void Initialize()
_aapl = AddEquity("AAPL", Resolution.Minute, extendedMarketHours: true, dataNormalizationMode: DataNormalizationMode.Raw).Symbol;
var option = AddOption(_aapl, Resolution.Minute);
- option.SetFilter(-1, +1, 0, 365);
+ option.SetFilter(u => u.StandardsOnly().Strikes(-1, +1).Expiration(0, 365));
}
public override void OnData(Slice slice)
diff --git a/Algorithm.CSharp/OptionPriceModelForSupportedAmericanOptionRegressionAlgorithm.cs b/Algorithm.CSharp/OptionPriceModelForSupportedAmericanOptionRegressionAlgorithm.cs
index 71649af269ac..dbf8825d462f 100644
--- a/Algorithm.CSharp/OptionPriceModelForSupportedAmericanOptionRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionPriceModelForSupportedAmericanOptionRegressionAlgorithm.cs
@@ -30,6 +30,8 @@ public override void Initialize()
SetEndDate(2014, 6, 9);
var option = AddOption("AAPL", Resolution.Minute);
+ option.SetFilter(u => u.StandardsOnly().Strikes(-1, 1).Expiration(0, 35));
+
// BaroneAdesiWhaley model supports American style options
option.PriceModel = OptionPriceModels.BaroneAdesiWhaley();
diff --git a/Algorithm.CSharp/OptionPriceModelForUnsupportedAmericanOptionRegressionAlgorithm.cs b/Algorithm.CSharp/OptionPriceModelForUnsupportedAmericanOptionRegressionAlgorithm.cs
index d5873252e3f6..ca1764623e9c 100644
--- a/Algorithm.CSharp/OptionPriceModelForUnsupportedAmericanOptionRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionPriceModelForUnsupportedAmericanOptionRegressionAlgorithm.cs
@@ -29,6 +29,8 @@ public override void Initialize()
SetEndDate(2014, 6, 9);
var option = AddOption("AAPL", Resolution.Minute);
+ option.SetFilter(u => u.StandardsOnly().Strikes(-1, 1).Expiration(0, 35));
+
// BlackSholes model does not support American style options
option.PriceModel = OptionPriceModels.BlackScholes();
diff --git a/Algorithm.CSharp/OptionRenameDailyRegressionAlgorithm.cs b/Algorithm.CSharp/OptionRenameDailyRegressionAlgorithm.cs
index 0c42dd193bdc..198bb8098250 100644
--- a/Algorithm.CSharp/OptionRenameDailyRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionRenameDailyRegressionAlgorithm.cs
@@ -194,10 +194,10 @@ public override void OnOrderEvent(OrderEvent orderEvent)
{"Treynor Ratio", "0"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$0"},
- {"Lowest Capacity Asset", "NWSA VJ5IKAXU7WBQ|NWSA T3MO1488O0H1"},
+ {"Lowest Capacity Asset", "NWSA VJ5IKAXUC6NA|NWSA T3MO1488O0H1"},
{"Portfolio Turnover", "0.06%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "4dc221b1c1461ada80a8d494dd8f2610"}
+ {"OrderListHash", "bab17a4489f3ecf79df28e661de80a9f"}
};
}
}
diff --git a/Algorithm.CSharp/OptionRenameRegressionAlgorithm.cs b/Algorithm.CSharp/OptionRenameRegressionAlgorithm.cs
index 135aef3adfcb..180898b9cea5 100644
--- a/Algorithm.CSharp/OptionRenameRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionRenameRegressionAlgorithm.cs
@@ -182,10 +182,10 @@ public override void OnOrderEvent(OrderEvent orderEvent)
{"Treynor Ratio", "0"},
{"Total Fees", "$4.00"},
{"Estimated Strategy Capacity", "$8600000.00"},
- {"Lowest Capacity Asset", "NWSA VJ5IKAXU7WBQ|NWSA T3MO1488O0H1"},
+ {"Lowest Capacity Asset", "NWSA VJ5IKAXUC6NA|NWSA T3MO1488O0H1"},
{"Portfolio Turnover", "0.13%"},
{"Drawdown Recovery", "2"},
- {"OrderListHash", "83dfb4b2f1d41429273d83335b63426c"}
+ {"OrderListHash", "9e6589151844ae971e04a44a72fb80cd"}
};
}
}
diff --git a/Algorithm.CSharp/OptionResolutionRegressionAlgorithm.cs b/Algorithm.CSharp/OptionResolutionRegressionAlgorithm.cs
index 7e46616f0da3..0631ad5f606b 100644
--- a/Algorithm.CSharp/OptionResolutionRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionResolutionRegressionAlgorithm.cs
@@ -38,7 +38,7 @@ public override void Initialize()
UniverseSettings.Resolution = Resolution.Daily;
var option = AddOption("GOOG");
- option.SetFilter(u => u.Strikes(-2, +2).Expiration(0, 180));
+ option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2).Expiration(0, 180));
_optionSymbol = option.Symbol;
if (UniverseManager.TryGetValue(option.Symbol, out var universe)
@@ -132,7 +132,7 @@ public override void OnData(Slice slice)
{"Lowest Capacity Asset", ""},
{"Portfolio Turnover", "0%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "ce4cdd4d05199b633559cd14bc6db237"}
+ {"OrderListHash", "2a63ba11c7395ae4f7b710aa3a64c71a"}
};
}
}
diff --git a/Algorithm.CSharp/OptionShortCallMarginCallEventsAlgorithm.cs b/Algorithm.CSharp/OptionShortCallMarginCallEventsAlgorithm.cs
index fe34a43b590f..6192dc406e60 100644
--- a/Algorithm.CSharp/OptionShortCallMarginCallEventsAlgorithm.cs
+++ b/Algorithm.CSharp/OptionShortCallMarginCallEventsAlgorithm.cs
@@ -42,7 +42,7 @@ public override void Initialize()
var option = AddOption(equitySymbol);
_optionSymbol = option.Symbol;
- option.SetFilter(u => u.Strikes(-2, +2)
+ option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2)
.Expiration(0, 180));
Portfolio.MarginCallModel = new CustomMarginCallModel(Portfolio, DefaultOrderProperties);
@@ -120,10 +120,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "-2.981"},
{"Total Fees", "$7.50"},
{"Estimated Strategy Capacity", "$66000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZFMML01JA|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZFMML4BUU|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "1.01%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "98d7ad800db7b97a373ca7edc56e3223"}
+ {"OrderListHash", "039fb1adfb5366ea629e3f5e0646ab8b"}
};
}
}
diff --git a/Algorithm.CSharp/OptionSplitRegressionAlgorithm.cs b/Algorithm.CSharp/OptionSplitRegressionAlgorithm.cs
index 00f0d8012051..b15887f61377 100644
--- a/Algorithm.CSharp/OptionSplitRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionSplitRegressionAlgorithm.cs
@@ -165,10 +165,10 @@ public override void OnOrderEvent(OrderEvent orderEvent)
{"Treynor Ratio", "0"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$88000.00"},
- {"Lowest Capacity Asset", "AAPL VRCWOCTRR37Q|AAPL R735QTJ8XC9X"},
+ {"Lowest Capacity Asset", "AAPL VRCWOCTRVDJA|AAPL R735QTJ8XC9X"},
{"Portfolio Turnover", "0.04%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "75e0d3e5d72502421287925c55de3054"}
+ {"OrderListHash", "6753be1c117f9528f920eb84976a070f"}
};
}
}
diff --git a/Algorithm.CSharp/OptionSplitWarmupRegressionAlgorithm.cs b/Algorithm.CSharp/OptionSplitWarmupRegressionAlgorithm.cs
index 92bc551ea1a2..98ffa66a4c14 100644
--- a/Algorithm.CSharp/OptionSplitWarmupRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionSplitWarmupRegressionAlgorithm.cs
@@ -39,6 +39,7 @@ public override void Initialize()
SetEndDate(2014, 06, 09);
var option = AddOption("AAPL");
+ option.SetFilter(u => u.StandardsOnly().Strikes(-1, 1).Expiration(0, 35));
_optionSymbol = option.Symbol;
var optionContractSymbol = OptionChain(_optionSymbol)
diff --git a/Algorithm.CSharp/OptionStrategyFactoryMethodsBaseAlgorithm.cs b/Algorithm.CSharp/OptionStrategyFactoryMethodsBaseAlgorithm.cs
index d7e486765ee1..7f61a98a815f 100644
--- a/Algorithm.CSharp/OptionStrategyFactoryMethodsBaseAlgorithm.cs
+++ b/Algorithm.CSharp/OptionStrategyFactoryMethodsBaseAlgorithm.cs
@@ -45,7 +45,7 @@ public override void Initialize()
var option = AddOption("GOOG");
_optionSymbol = option.Symbol;
- option.SetFilter(-2, +2, 0, 180);
+ option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2).Expiration(0, 180));
SetBenchmark("GOOG");
}
@@ -67,8 +67,7 @@ public override void OnData(Slice slice)
var buyingPowerModel = positionGroup.BuyingPowerModel as OptionStrategyPositionGroupBuyingPowerModel;
if (buyingPowerModel == null)
{
- throw new RegressionTestException($@"Expected position group buying power model type: {nameof(OptionStrategyPositionGroupBuyingPowerModel)
- }. Actual: {positionGroup.BuyingPowerModel.GetType()}");
+ throw new RegressionTestException($@"Expected position group buying power model type: {nameof(OptionStrategyPositionGroupBuyingPowerModel)}. Actual: {positionGroup.BuyingPowerModel.GetType()}");
}
AssertStrategyPositionGroup(positionGroup);
@@ -91,9 +90,7 @@ public override void OnEndOfAlgorithm()
var ordersCount = Transactions.GetOrders((order) => order.Status == OrderStatus.Filled).Count();
if (ordersCount != ExpectedOrdersCount)
{
- throw new RegressionTestException($@"Expected {ExpectedOrdersCount
- } orders to have been submitted and filled, half for buying the strategy and the other half for the liquidation. Actual {
- ordersCount}");
+ throw new RegressionTestException($@"Expected {ExpectedOrdersCount} orders to have been submitted and filled, half for buying the strategy and the other half for the liquidation. Actual {ordersCount}");
}
}
diff --git a/Algorithm.CSharp/OptionStrategyFilteringUniverseBoxSpreadRegressionAlgorithm.cs b/Algorithm.CSharp/OptionStrategyFilteringUniverseBoxSpreadRegressionAlgorithm.cs
index cc1eed036bd0..8b7f4342044f 100644
--- a/Algorithm.CSharp/OptionStrategyFilteringUniverseBoxSpreadRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionStrategyFilteringUniverseBoxSpreadRegressionAlgorithm.cs
@@ -125,10 +125,10 @@ protected override void TestFiltering(OptionChain chain)
{"Treynor Ratio", "0"},
{"Total Fees", "$4.00"},
{"Estimated Strategy Capacity", "$3600000.00"},
- {"Lowest Capacity Asset", "GOOCV 306JVPQ5YT51I|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 306JVPQ5YXFD2|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "3.66%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "b498b296357ad672073c12dce73be212"}
+ {"OrderListHash", "b8f487d284100b6fe8cf84b0bcbd5941"}
};
}
}
diff --git a/Algorithm.CSharp/OptionStrategyFilteringUniverseCallButterflyRegressionAlgorithm.cs b/Algorithm.CSharp/OptionStrategyFilteringUniverseCallButterflyRegressionAlgorithm.cs
index 940b188dd074..4298de39e68c 100644
--- a/Algorithm.CSharp/OptionStrategyFilteringUniverseCallButterflyRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionStrategyFilteringUniverseCallButterflyRegressionAlgorithm.cs
@@ -121,10 +121,10 @@ protected override void TestFiltering(OptionChain chain)
{"Treynor Ratio", "0"},
{"Total Fees", "$3.30"},
{"Estimated Strategy Capacity", "$4000000.00"},
- {"Lowest Capacity Asset", "GOOCV W7FVK9Q85UPY|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W7FVK9Q8A51I|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "3.86%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "4aa7b753745ce198ab5c92ab730ddb06"}
+ {"OrderListHash", "8588e9d994886ac2d6118ec7bd99a37b"}
};
}
}
diff --git a/Algorithm.CSharp/OptionStrategyFilteringUniverseCallCalendarSpreadRegressionAlgorithm.cs b/Algorithm.CSharp/OptionStrategyFilteringUniverseCallCalendarSpreadRegressionAlgorithm.cs
index 4af060b69fb6..d2af342853e7 100644
--- a/Algorithm.CSharp/OptionStrategyFilteringUniverseCallCalendarSpreadRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionStrategyFilteringUniverseCallCalendarSpreadRegressionAlgorithm.cs
@@ -114,10 +114,10 @@ protected override void TestFiltering(OptionChain chain)
{"Treynor Ratio", "0"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$1700000.00"},
- {"Lowest Capacity Asset", "GOOCV W7TNTL2UX5FQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W7TNTL2V1FRA|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "2.58%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "8a33a4fad0585112f230f75f03e0c2fd"}
+ {"OrderListHash", "89f5088049017cdefcda5b924f142ce6"}
};
}
}
diff --git a/Algorithm.CSharp/OptionStrategyFilteringUniverseCallLadderRegressionAlgorithm.cs b/Algorithm.CSharp/OptionStrategyFilteringUniverseCallLadderRegressionAlgorithm.cs
index 340180b2112c..638b1e5815f2 100644
--- a/Algorithm.CSharp/OptionStrategyFilteringUniverseCallLadderRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionStrategyFilteringUniverseCallLadderRegressionAlgorithm.cs
@@ -121,10 +121,10 @@ protected override void TestFiltering(OptionChain chain)
{"Treynor Ratio", "0"},
{"Total Fees", "$3.00"},
{"Estimated Strategy Capacity", "$11000000.00"},
- {"Lowest Capacity Asset", "GOOCV W7FVKA6RJBNQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W7FVKA6RNLZA|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "2.97%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "73508fbc2c2f4ee3ffdb4dc653717205"}
+ {"OrderListHash", "a6e4aef493f4429caa9e7495e944a77a"}
};
}
}
diff --git a/Algorithm.CSharp/OptionStrategyFilteringUniverseCallSpreadRegressionAlgorithm.cs b/Algorithm.CSharp/OptionStrategyFilteringUniverseCallSpreadRegressionAlgorithm.cs
index 6b62f1497000..c287102901e4 100644
--- a/Algorithm.CSharp/OptionStrategyFilteringUniverseCallSpreadRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionStrategyFilteringUniverseCallSpreadRegressionAlgorithm.cs
@@ -114,10 +114,10 @@ protected override void TestFiltering(OptionChain chain)
{"Treynor Ratio", "0"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$10000000.00"},
- {"Lowest Capacity Asset", "GOOCV W7FVKA6RJBNQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W7FVKA6RNLZA|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "2.09%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "8efb4594409cb11fc8b25a1eedb2b3e3"}
+ {"OrderListHash", "0e99ad3d24cce65429344fcbc810923d"}
};
}
}
diff --git a/Algorithm.CSharp/OptionStrategyFilteringUniverseConversionRegressionAlgorithm.cs b/Algorithm.CSharp/OptionStrategyFilteringUniverseConversionRegressionAlgorithm.cs
index f4e2c167fe6f..b08201bcacb8 100644
--- a/Algorithm.CSharp/OptionStrategyFilteringUniverseConversionRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionStrategyFilteringUniverseConversionRegressionAlgorithm.cs
@@ -113,10 +113,10 @@ protected override void TestFiltering(OptionChain chain)
{"Treynor Ratio", "0"},
{"Total Fees", "$3.00"},
{"Estimated Strategy Capacity", "$15000000.00"},
- {"Lowest Capacity Asset", "GOOCV W7FVK9Q85UPY|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W7FVK9Q8A51I|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "39.39%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "6fb9441bb0f49a1af2fb73dac30c5982"}
+ {"OrderListHash", "c5615899d622d94d8b1d8a8a416977f6"}
};
}
}
diff --git a/Algorithm.CSharp/OptionStrategyFilteringUniverseIronCondorRegressionAlgorithm.cs b/Algorithm.CSharp/OptionStrategyFilteringUniverseIronCondorRegressionAlgorithm.cs
index 9c9a84039d0f..163cb4e90f4d 100644
--- a/Algorithm.CSharp/OptionStrategyFilteringUniverseIronCondorRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionStrategyFilteringUniverseIronCondorRegressionAlgorithm.cs
@@ -127,10 +127,10 @@ protected override void TestFiltering(OptionChain chain)
{"Treynor Ratio", "0"},
{"Total Fees", "$4.00"},
{"Estimated Strategy Capacity", "$3400000.00"},
- {"Lowest Capacity Asset", "GOOCV 306JVPPH5QXMU|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 306JVPPH5V7YE|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "2.76%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "5162055c872b1954d3c51d05391defc3"}
+ {"OrderListHash", "8a30c50c7eb8b1b63067a6c17481ea9f"}
};
}
}
diff --git a/Algorithm.CSharp/OptionStrategyFilteringUniverseJellyRollRegressionAlgorithm.cs b/Algorithm.CSharp/OptionStrategyFilteringUniverseJellyRollRegressionAlgorithm.cs
index c7a5d3fb9f3c..299ad4135349 100644
--- a/Algorithm.CSharp/OptionStrategyFilteringUniverseJellyRollRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionStrategyFilteringUniverseJellyRollRegressionAlgorithm.cs
@@ -125,10 +125,10 @@ protected override void TestFiltering(OptionChain chain)
{"Treynor Ratio", "0"},
{"Total Fees", "$4.00"},
{"Estimated Strategy Capacity", "$3200000.00"},
- {"Lowest Capacity Asset", "GOOCV W7TNTL2UX5FQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W7TNTL2V1FRA|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "4.92%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "5945821ac297e6e39dfd8549af06ba12"}
+ {"OrderListHash", "7f6c8cf903d0982b244c4c7fc55f9941"}
};
}
}
diff --git a/Algorithm.CSharp/OptionStrategyFilteringUniverseProtectiveCollarRegressionAlgorithm.cs b/Algorithm.CSharp/OptionStrategyFilteringUniverseProtectiveCollarRegressionAlgorithm.cs
index afde48ee186e..99ff1aee0878 100644
--- a/Algorithm.CSharp/OptionStrategyFilteringUniverseProtectiveCollarRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionStrategyFilteringUniverseProtectiveCollarRegressionAlgorithm.cs
@@ -114,10 +114,10 @@ protected override void TestFiltering(OptionChain chain)
{"Treynor Ratio", "0"},
{"Total Fees", "$3.00"},
{"Estimated Strategy Capacity", "$38000000.00"},
- {"Lowest Capacity Asset", "GOOCV 306JVPQ5YT51I|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 306JVPQ5YXFD2|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "39.24%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "6bbae139ff483b232448a003383f296a"}
+ {"OrderListHash", "92255bb1d24205b620441d2bb1f21f04"}
};
}
}
diff --git a/Algorithm.CSharp/OptionStrategyFilteringUniversePutButterflyRegressionAlgorithm.cs b/Algorithm.CSharp/OptionStrategyFilteringUniversePutButterflyRegressionAlgorithm.cs
index ea31ee639136..f7663e701b3b 100644
--- a/Algorithm.CSharp/OptionStrategyFilteringUniversePutButterflyRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionStrategyFilteringUniversePutButterflyRegressionAlgorithm.cs
@@ -121,10 +121,10 @@ protected override void TestFiltering(OptionChain chain)
{"Treynor Ratio", "0"},
{"Total Fees", "$3.30"},
{"Estimated Strategy Capacity", "$3400000.00"},
- {"Lowest Capacity Asset", "GOOCV 306JVPQ5YT51I|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 306JVPQ5YXFD2|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "3.43%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "4d232421a55b71dd93e47e25fff3eff7"}
+ {"OrderListHash", "f7baa1f5e8b8a9f59563487c1cdd08fa"}
};
}
}
diff --git a/Algorithm.CSharp/OptionStrategyFilteringUniversePutCalendarSpreadRegressionAlgorithm.cs b/Algorithm.CSharp/OptionStrategyFilteringUniversePutCalendarSpreadRegressionAlgorithm.cs
index d1d75e103fa0..71ff5e467538 100644
--- a/Algorithm.CSharp/OptionStrategyFilteringUniversePutCalendarSpreadRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionStrategyFilteringUniversePutCalendarSpreadRegressionAlgorithm.cs
@@ -114,10 +114,10 @@ protected override void TestFiltering(OptionChain chain)
{"Treynor Ratio", "0"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$9100000.00"},
- {"Lowest Capacity Asset", "GOOCV 306JVPPXP4EKM|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 306JVPPXP8OW6|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "2.36%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "d2ff169cdbd21d4229b6381e5417fd33"}
+ {"OrderListHash", "e7c580fc19e2cc545c96277031b9d9ed"}
};
}
}
diff --git a/Algorithm.CSharp/OptionStrategyFilteringUniversePutLadderRegressionAlgorithm.cs b/Algorithm.CSharp/OptionStrategyFilteringUniversePutLadderRegressionAlgorithm.cs
index 27579dc6ac33..665a357ab517 100644
--- a/Algorithm.CSharp/OptionStrategyFilteringUniversePutLadderRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionStrategyFilteringUniversePutLadderRegressionAlgorithm.cs
@@ -121,10 +121,10 @@ protected override void TestFiltering(OptionChain chain)
{"Treynor Ratio", "0"},
{"Total Fees", "$3.00"},
{"Estimated Strategy Capacity", "$2900000.00"},
- {"Lowest Capacity Asset", "GOOCV 306JVPPH5QXMU|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 306JVPPH5V7YE|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "2.43%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "96a0b3dbc7070c667a169459d24ec28e"}
+ {"OrderListHash", "e8cbf8de4fe77a51f7b09c123d865d09"}
};
}
}
diff --git a/Algorithm.CSharp/OptionStrategyFilteringUniversePutSpreadRegressionAlgorithm.cs b/Algorithm.CSharp/OptionStrategyFilteringUniversePutSpreadRegressionAlgorithm.cs
index f6b4ed370cb8..f46cc19839e0 100644
--- a/Algorithm.CSharp/OptionStrategyFilteringUniversePutSpreadRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionStrategyFilteringUniversePutSpreadRegressionAlgorithm.cs
@@ -114,10 +114,10 @@ protected override void TestFiltering(OptionChain chain)
{"Treynor Ratio", "0"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$1900000.00"},
- {"Lowest Capacity Asset", "GOOCV 306JVPPH5QXMU|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 306JVPPH5V7YE|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "1.60%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "7600923ed8d7dae66e7827fde5421cbe"}
+ {"OrderListHash", "4631d091180d27a2eaa4cdc06c6f4044"}
};
}
}
diff --git a/Algorithm.CSharp/OptionStrategyFilteringUniverseSingleCallRegressionAlgorithm.cs b/Algorithm.CSharp/OptionStrategyFilteringUniverseSingleCallRegressionAlgorithm.cs
index e2e62e96cb03..5821a6c71143 100644
--- a/Algorithm.CSharp/OptionStrategyFilteringUniverseSingleCallRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionStrategyFilteringUniverseSingleCallRegressionAlgorithm.cs
@@ -107,10 +107,10 @@ protected override void TestFiltering(OptionChain chain)
{"Treynor Ratio", "0"},
{"Total Fees", "$1.00"},
{"Estimated Strategy Capacity", "$9500000.00"},
- {"Lowest Capacity Asset", "GOOCV W7FVK9YHUL6U|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W7FVK9YHYVIE|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "0.87%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "05291a87003539134cf529870851206f"}
+ {"OrderListHash", "50acbede042747f30c4fe8cae47a84c0"}
};
}
}
diff --git a/Algorithm.CSharp/OptionStrategyFilteringUniverseSinglePutRegressionAlgorithm.cs b/Algorithm.CSharp/OptionStrategyFilteringUniverseSinglePutRegressionAlgorithm.cs
index 70ff6327cb34..578af95cd55e 100644
--- a/Algorithm.CSharp/OptionStrategyFilteringUniverseSinglePutRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionStrategyFilteringUniverseSinglePutRegressionAlgorithm.cs
@@ -107,10 +107,10 @@ protected override void TestFiltering(OptionChain chain)
{"Treynor Ratio", "0"},
{"Total Fees", "$1.00"},
{"Estimated Strategy Capacity", "$8100000.00"},
- {"Lowest Capacity Asset", "GOOCV 306JVPPXP4EKM|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 306JVPPXP8OW6|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "0.77%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "5ebd6e00d06329e3c7151407527e449f"}
+ {"OrderListHash", "c16233245f4266df677d9bf5d0ec2e43"}
};
}
}
diff --git a/Algorithm.CSharp/OptionStrategyFilteringUniverseStraddleRegressionAlgorithm.cs b/Algorithm.CSharp/OptionStrategyFilteringUniverseStraddleRegressionAlgorithm.cs
index 382b9f70fef5..61bd7c7bce4f 100644
--- a/Algorithm.CSharp/OptionStrategyFilteringUniverseStraddleRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionStrategyFilteringUniverseStraddleRegressionAlgorithm.cs
@@ -112,10 +112,10 @@ protected override void TestFiltering(OptionChain chain)
{"Treynor Ratio", "0"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$2400000.00"},
- {"Lowest Capacity Asset", "GOOCV 306JVPPXP4EKM|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 306JVPPXP8OW6|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "1.99%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "6d7049bd413081a2ece8609841aebe02"}
+ {"OrderListHash", "cb036434acd9a61cb85bd4b2b5671b79"}
};
}
}
diff --git a/Algorithm.CSharp/OptionStrategyFilteringUniverseStrangleRegressionAlgorithm.cs b/Algorithm.CSharp/OptionStrategyFilteringUniverseStrangleRegressionAlgorithm.cs
index 87f99da0b489..8150e7842b0f 100644
--- a/Algorithm.CSharp/OptionStrategyFilteringUniverseStrangleRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionStrategyFilteringUniverseStrangleRegressionAlgorithm.cs
@@ -113,10 +113,10 @@ protected override void TestFiltering(OptionChain chain)
{"Treynor Ratio", "0"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$2000000.00"},
- {"Lowest Capacity Asset", "GOOCV 306JVPPH5QXMU|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 306JVPPH5V7YE|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "1.64%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "dcae5f3a4eadd9acf5a72f6cf4b386a1"}
+ {"OrderListHash", "e0599c7737867243d62b3b3311535842"}
};
}
}
diff --git a/Algorithm.CSharp/OptionStrategyMarginCallEventsAlgorithm.cs b/Algorithm.CSharp/OptionStrategyMarginCallEventsAlgorithm.cs
index c2985e1b9662..14ab078411c5 100644
--- a/Algorithm.CSharp/OptionStrategyMarginCallEventsAlgorithm.cs
+++ b/Algorithm.CSharp/OptionStrategyMarginCallEventsAlgorithm.cs
@@ -143,7 +143,7 @@ public override void OnMarginCall(List requests)
{"Treynor Ratio", "0"},
{"Total Fees", "$1252.00"},
{"Estimated Strategy Capacity", "$130000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZFMML01JA|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZFMML4BUU|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "1.17%"},
{"OrderListHash", "681be68373c2f38e51456d7f8010e7d3"}
};
diff --git a/Algorithm.CSharp/OptionSymbolCanonicalRegressionAlgorithm.cs b/Algorithm.CSharp/OptionSymbolCanonicalRegressionAlgorithm.cs
index 3e3e09fe3b62..7d625a1bc535 100644
--- a/Algorithm.CSharp/OptionSymbolCanonicalRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionSymbolCanonicalRegressionAlgorithm.cs
@@ -118,10 +118,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "0"},
{"Total Fees", "$1.00"},
{"Estimated Strategy Capacity", "$5700000.00"},
- {"Lowest Capacity Asset", "AOL VRKS95ENLBYE|AOL R735QTJ8XC9X"},
+ {"Lowest Capacity Asset", "AOL VRKS95ENPM9Y|AOL R735QTJ8XC9X"},
{"Portfolio Turnover", "0.59%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "cf5752ad13afe5294a9a8aad660d015a"}
+ {"OrderListHash", "4351c4e0db0da9c6c9e032a08ee861ff"}
};
}
}
diff --git a/Algorithm.CSharp/OptionTimeSliceRegressionAlgorithm.cs b/Algorithm.CSharp/OptionTimeSliceRegressionAlgorithm.cs
index 54aefbded57b..07de16a12246 100644
--- a/Algorithm.CSharp/OptionTimeSliceRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OptionTimeSliceRegressionAlgorithm.cs
@@ -86,12 +86,12 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 10857;
+ public long DataPoints => 10869;
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 787;
+ public int AlgorithmHistoryDataPoints => 788;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/OptionsAutomaticSeedRegressionAlgorithm.cs b/Algorithm.CSharp/OptionsAutomaticSeedRegressionAlgorithm.cs
new file mode 100644
index 000000000000..b864cf8823a0
--- /dev/null
+++ b/Algorithm.CSharp/OptionsAutomaticSeedRegressionAlgorithm.cs
@@ -0,0 +1,101 @@
+/*
+ * 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 QuantConnect.Data;
+using QuantConnect.Data.UniverseSelection;
+
+namespace QuantConnect.Algorithm.CSharp
+{
+ ///
+ /// Regression algorithm asserting that option contracts added via universe selection get automatically seeded by default
+ ///
+ public class OptionsAutomaticSeedRegressionAlgorithm : AutomaticSeedBaseRegressionAlgorithm
+ {
+ private bool _contractsAdded;
+
+ protected override bool ShouldHaveTradeData => true;
+ protected override bool ShouldHaveQuoteData => true;
+ protected override bool ShouldHaveOpenInterestData => true;
+
+ public override void Initialize()
+ {
+ SetStartDate(2015, 12, 28);
+ SetEndDate(2015, 12, 28);
+ SetCash(100000);
+
+ Settings.SeedInitialPrices = true;
+ UniverseSettings.Resolution = Resolution.Minute;
+
+ var equity = AddEquity("GOOG");
+
+ // This security should haven been seeded right away
+ if (!equity.HasData || equity.Price == 0)
+ {
+ throw new RegressionTestException("Equity security was not seeded");
+ }
+
+ var option = AddOption(equity.Symbol);
+
+ option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2).Expiration(0, 180));
+ }
+
+ public override void OnData(Slice slice)
+ {
+ if (Time.TimeOfDay.Hours > 12)
+ {
+ var anotherEquity = AddEquity("SPY", Resolution.Daily);
+
+ // This security should haven been seeded right away
+ if (!anotherEquity.HasData || anotherEquity.Price == 0)
+ {
+ throw new RegressionTestException("Equity security was not seeded");
+ }
+ }
+ }
+
+ public override void OnSecuritiesChanged(SecurityChanges changes)
+ {
+ base.OnSecuritiesChanged(changes);
+
+ if (!_contractsAdded)
+ {
+ foreach (var addedSecurity in changes.AddedSecurities)
+ {
+ // Just making sure we had the data to select and seed options
+ _contractsAdded |= addedSecurity.Symbol.SecurityType == SecurityType.Option;
+ }
+ }
+ }
+
+ public override void OnEndOfAlgorithm()
+ {
+ if (!_contractsAdded)
+ {
+ throw new RegressionTestException("No option contracts were added");
+ }
+ }
+
+ ///
+ /// Data Points count of all timeslices of algorithm
+ ///
+ public override long DataPoints => 4044;
+
+ ///
+ /// Data Points count of the algorithm history
+ ///
+ public override int AlgorithmHistoryDataPoints => 218;
+ }
+}
diff --git a/Algorithm.CSharp/OptionsExpiredContractRegression.cs b/Algorithm.CSharp/OptionsExpiredContractRegression.cs
index fbe53061f5b9..6ce621e6bdfb 100644
--- a/Algorithm.CSharp/OptionsExpiredContractRegression.cs
+++ b/Algorithm.CSharp/OptionsExpiredContractRegression.cs
@@ -40,7 +40,7 @@ public override void Initialize()
// Subscribe to GOOG Options
var option = AddOption("GOOG");
- option.SetFilter(x => x.CallsOnly().Strikes(0, 1).Expiration(0, 30));
+ option.SetFilter(x => x.StandardsOnly().CallsOnly().Strikes(0, 1).Expiration(0, 30));
}
public override void OnData(Slice slice)
diff --git a/Algorithm.CSharp/OrderSubmissionDataRegressionAlgorithm.cs b/Algorithm.CSharp/OrderSubmissionDataRegressionAlgorithm.cs
index 0e1112e41ec0..5fb54088b678 100644
--- a/Algorithm.CSharp/OrderSubmissionDataRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/OrderSubmissionDataRegressionAlgorithm.cs
@@ -86,7 +86,7 @@ private void PlaceTrade(string ticker)
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 60;
+ public int AlgorithmHistoryDataPoints => 5;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/ProcessSplitSymbolsRegressionAlgorithm.cs b/Algorithm.CSharp/ProcessSplitSymbolsRegressionAlgorithm.cs
index d30f037031ad..1be6bc4b2db4 100644
--- a/Algorithm.CSharp/ProcessSplitSymbolsRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/ProcessSplitSymbolsRegressionAlgorithm.cs
@@ -73,7 +73,7 @@ public override void OnData(Slice slice)
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 34;
+ public long DataPoints => 35;
///
/// Data Points count of the algorithm history
diff --git a/Algorithm.CSharp/QuantConnect.Algorithm.CSharp.csproj b/Algorithm.CSharp/QuantConnect.Algorithm.CSharp.csproj
index 358d8f7d7de5..318f77c54be4 100644
--- a/Algorithm.CSharp/QuantConnect.Algorithm.CSharp.csproj
+++ b/Algorithm.CSharp/QuantConnect.Algorithm.CSharp.csproj
@@ -4,7 +4,7 @@
AnyCPU
QuantConnect.Algorithm.CSharp
QuantConnect.Algorithm.CSharp
- net9.0
+ net10.0
false
bin\$(Configuration)\
AllEnabledByDefault
@@ -32,7 +32,7 @@
portable
-
+
diff --git a/Algorithm.CSharp/RegressionTests/Collective2IndexOptionAlgorithm.cs b/Algorithm.CSharp/RegressionTests/Collective2IndexOptionAlgorithm.cs
index 0f1bb5158255..bddb8bfe1e39 100644
--- a/Algorithm.CSharp/RegressionTests/Collective2IndexOptionAlgorithm.cs
+++ b/Algorithm.CSharp/RegressionTests/Collective2IndexOptionAlgorithm.cs
@@ -115,7 +115,7 @@ public override void OnData(Slice slice)
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 4543;
+ public long DataPoints => 4544;
///
/// Data Points count of the algorithm history
@@ -151,10 +151,10 @@ public override void OnData(Slice slice)
{"Treynor Ratio", "5.946"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$8000.00"},
- {"Lowest Capacity Asset", "SPXW XKX6S2GM9PGU|SPX 31"},
+ {"Lowest Capacity Asset", "SPXW XKX6S2GMDZSE|SPX 31"},
{"Portfolio Turnover", "0.01%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "44d9880b19d4709447faf505d24aad7f"}
+ {"OrderListHash", "ad9c0f3aa3b311065df12bcff9a2b4de"}
};
}
}
diff --git a/Algorithm.CSharp/RegressionTests/CorrelationLastComputedValueRegressionAlgorithm.cs b/Algorithm.CSharp/RegressionTests/CorrelationLastComputedValueRegressionAlgorithm.cs
index e532ef49817b..2989c9dbdc6c 100644
--- a/Algorithm.CSharp/RegressionTests/CorrelationLastComputedValueRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/RegressionTests/CorrelationLastComputedValueRegressionAlgorithm.cs
@@ -97,7 +97,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 72;
+ public int AlgorithmHistoryDataPoints => 21;
///
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
diff --git a/Algorithm.CSharp/RegressionTests/CustomData/CustomDataUnlinkedTradeBarIconicTypeConsolidationRegressionAlgorithm.cs b/Algorithm.CSharp/RegressionTests/CustomData/CustomDataUnlinkedTradeBarIconicTypeConsolidationRegressionAlgorithm.cs
index ffc4d735b3fb..650cff0faf4d 100644
--- a/Algorithm.CSharp/RegressionTests/CustomData/CustomDataUnlinkedTradeBarIconicTypeConsolidationRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/RegressionTests/CustomData/CustomDataUnlinkedTradeBarIconicTypeConsolidationRegressionAlgorithm.cs
@@ -66,7 +66,7 @@ public override void OnData(Slice slice)
///
/// Incrementally updating data
///
- private class IncrementallyGeneratedCustomData : UnlinkedDataTradeBar
+ public class IncrementallyGeneratedCustomData : UnlinkedDataTradeBar
{
private const decimal _start = 10.01m;
private static decimal _step;
diff --git a/Algorithm.CSharp/RegressionTests/Universes/ETFConstituentUniverseCompositeDelistingRegressionAlgorithm.cs b/Algorithm.CSharp/RegressionTests/Universes/ETFConstituentUniverseCompositeDelistingRegressionAlgorithm.cs
index 8bd9ea031de5..4b918fd42be9 100644
--- a/Algorithm.CSharp/RegressionTests/Universes/ETFConstituentUniverseCompositeDelistingRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/RegressionTests/Universes/ETFConstituentUniverseCompositeDelistingRegressionAlgorithm.cs
@@ -106,18 +106,17 @@ public override void OnSecuritiesChanged(SecurityChanges changes)
}
// if we added the etf subscription it will get added and delisted and send us a addition/removal event
- var adjusment = AddETFSubscription ? 1 : 0;
- var expectedChangesCount = _universeSymbolCount + adjusment;
+ var expectedChangesCount = _universeSymbolCount;
if (_universeSelectionDone)
{
- // "_universeSymbolCount + 1" because selection is done right away,
- // so AddedSecurities includes all ETF constituents (including APPL) plus GDVD
- _universeAdded |= changes.AddedSecurities.Count == expectedChangesCount;
+ // manually added securities are added right away, the etf universe selection happens a few days later when data available
+ // AAPL was already added so it wont be counted
+ _universeAdded |= changes.AddedSecurities.Count == (expectedChangesCount - 1);
}
// TODO: shouldn't be sending AAPL as a removed security since it was added by another universe
- _universeRemoved |= changes.RemovedSecurities.Count == expectedChangesCount &&
+ _universeRemoved |= changes.RemovedSecurities.Count == (expectedChangesCount + (AddETFSubscription ? 1 : 0)) &&
UtcTime.Date >= _delistingDate &&
UtcTime.Date < EndDate;
}
@@ -151,7 +150,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public virtual long DataPoints => 692;
+ public virtual long DataPoints => 826;
///
/// Data Points count of the algorithm history
@@ -171,31 +170,31 @@ public override void OnEndOfAlgorithm()
{"Total Orders", "1"},
{"Average Win", "0%"},
{"Average Loss", "0%"},
- {"Compounding Annual Return", "30.084%"},
+ {"Compounding Annual Return", "26.315%"},
{"Drawdown", "5.400%"},
{"Expectancy", "0"},
{"Start Equity", "100000"},
- {"End Equity", "104393.19"},
- {"Net Profit", "4.393%"},
- {"Sharpe Ratio", "1.543"},
- {"Sortino Ratio", "2.111"},
- {"Probabilistic Sharpe Ratio", "58.028%"},
+ {"End Equity", "103892.62"},
+ {"Net Profit", "3.893%"},
+ {"Sharpe Ratio", "1.291"},
+ {"Sortino Ratio", "1.876"},
+ {"Probabilistic Sharpe Ratio", "53.929%"},
{"Loss Rate", "0%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
- {"Alpha", "0.166"},
- {"Beta", "0.717"},
- {"Annual Standard Deviation", "0.136"},
+ {"Alpha", "0.13"},
+ {"Beta", "0.697"},
+ {"Annual Standard Deviation", "0.139"},
{"Annual Variance", "0.019"},
- {"Information Ratio", "1.254"},
- {"Tracking Error", "0.118"},
- {"Treynor Ratio", "0.293"},
- {"Total Fees", "$2.06"},
- {"Estimated Strategy Capacity", "$160000000.00"},
+ {"Information Ratio", "0.889"},
+ {"Tracking Error", "0.122"},
+ {"Treynor Ratio", "0.257"},
+ {"Total Fees", "$2.04"},
+ {"Estimated Strategy Capacity", "$260000000.00"},
{"Lowest Capacity Asset", "AAPL R735QTJ8XC9X"},
{"Portfolio Turnover", "0.83%"},
{"Drawdown Recovery", "23"},
- {"OrderListHash", "527cba5cfdcac4b0f667bb354e80a1fe"}
+ {"OrderListHash", "cdf9a800c8ec7d5f9f750f32c2622f5a"}
};
}
}
diff --git a/Algorithm.CSharp/RegressionTests/Universes/ETFConstituentUniverseCompositeDelistingRegressionAlgorithmNoAddEquityETF.cs b/Algorithm.CSharp/RegressionTests/Universes/ETFConstituentUniverseCompositeDelistingRegressionAlgorithmNoAddEquityETF.cs
index 2b9499a1825b..213c17251b93 100644
--- a/Algorithm.CSharp/RegressionTests/Universes/ETFConstituentUniverseCompositeDelistingRegressionAlgorithmNoAddEquityETF.cs
+++ b/Algorithm.CSharp/RegressionTests/Universes/ETFConstituentUniverseCompositeDelistingRegressionAlgorithmNoAddEquityETF.cs
@@ -26,7 +26,7 @@ public class ETFConstituentUniverseCompositeDelistingRegressionAlgorithmNoAddEqu
///
/// Data Points count of all timeslices of algorithm
///
- public override long DataPoints => 511;
+ public override long DataPoints => 623;
///
/// Data Points count of the algorithm history
diff --git a/Algorithm.CSharp/RegressionTests/Universes/ETFConstituentUniverseMappedCompositeRegressionAlgorithm.cs b/Algorithm.CSharp/RegressionTests/Universes/ETFConstituentUniverseMappedCompositeRegressionAlgorithm.cs
index 976b6b4b1c4e..736c48767c7c 100644
--- a/Algorithm.CSharp/RegressionTests/Universes/ETFConstituentUniverseMappedCompositeRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/RegressionTests/Universes/ETFConstituentUniverseMappedCompositeRegressionAlgorithm.cs
@@ -157,7 +157,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 618;
+ public long DataPoints => 751;
///
/// Data Points count of the algorithm history
@@ -189,13 +189,13 @@ public override void OnEndOfAlgorithm()
{"Loss Rate", "0%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
- {"Alpha", "-0.084"},
- {"Beta", "0.591"},
+ {"Alpha", "-0.118"},
+ {"Beta", "0.445"},
{"Annual Standard Deviation", "0.078"},
{"Annual Variance", "0.006"},
- {"Information Ratio", "-1.408"},
- {"Tracking Error", "0.065"},
- {"Treynor Ratio", "-0.125"},
+ {"Information Ratio", "-2.01"},
+ {"Tracking Error", "0.086"},
+ {"Treynor Ratio", "-0.166"},
{"Total Fees", "$22.93"},
{"Estimated Strategy Capacity", "$74000000.00"},
{"Lowest Capacity Asset", "AAPL R735QTJ8XC9X"},
diff --git a/Algorithm.CSharp/RemoveUnderlyingRegressionAlgorithm.cs b/Algorithm.CSharp/RemoveUnderlyingRegressionAlgorithm.cs
index a7f60da76227..07d41de81a9d 100644
--- a/Algorithm.CSharp/RemoveUnderlyingRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/RemoveUnderlyingRegressionAlgorithm.cs
@@ -86,7 +86,7 @@ select optionContract
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 15885;
+ public long DataPoints => 15886;
///
/// Data Points count of the algorithm history
@@ -127,10 +127,10 @@ select optionContract
{"Treynor Ratio", "0"},
{"Total Fees", "$1.00"},
{"Estimated Strategy Capacity", "$28000.00"},
- {"Lowest Capacity Asset", "GOOCV 305RBQ2BZBZT2|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 305RBQ2BZGA4M|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "0.07%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "10acd880e4d9a4593efd155ba291c4e3"}
+ {"OrderListHash", "35f9749f41b6fd30dfcd6b74f172a93a"}
};
}
}
diff --git a/Algorithm.CSharp/RevertComboOrderPositionsAlgorithm.cs b/Algorithm.CSharp/RevertComboOrderPositionsAlgorithm.cs
index 75b20a65dcf5..ecbae4c6a7ad 100644
--- a/Algorithm.CSharp/RevertComboOrderPositionsAlgorithm.cs
+++ b/Algorithm.CSharp/RevertComboOrderPositionsAlgorithm.cs
@@ -49,6 +49,7 @@ public override void Initialize()
var equitySymbol = AddEquity("GOOG", leverage: 4, fillForward: true).Symbol;
_option = AddOption(equitySymbol, fillForward: true);
_option.SetFilter(optionFilterUniverse => optionFilterUniverse
+ .StandardsOnly()
.Strikes(-2, 2)
.Expiration(0, 180));
}
@@ -136,17 +137,13 @@ public override void OnEndOfAlgorithm()
var expectedEntryQuantity = leg.Quantity * _comboQuantity;
if (entryOrderTicket.Quantity != expectedEntryQuantity || entryOrderTicket.QuantityFilled != expectedEntryQuantity)
{
- throw new RegressionTestException($@"Entry order ticket quantity and filled quantity do not match expected quantity for leg {i
- }. Expected: {expectedEntryQuantity}. Actual quantity: {entryOrderTicket.Quantity}. Actual filled quantity: {
- entryOrderTicket.QuantityFilled}");
+ throw new RegressionTestException($@"Entry order ticket quantity and filled quantity do not match expected quantity for leg {i}. Expected: {expectedEntryQuantity}. Actual quantity: {entryOrderTicket.Quantity}. Actual filled quantity: {entryOrderTicket.QuantityFilled}");
}
var expectedExitQuantity = -expectedEntryQuantity;
if (exitOrderTicket.Quantity != expectedExitQuantity || exitOrderTicket.QuantityFilled != expectedExitQuantity)
{
- throw new RegressionTestException($@"Exit order ticket quantity and filled quantity do not match expected quantity for leg {i
- }. Expected: {expectedExitQuantity}. Actual quantity: {exitOrderTicket.Quantity}. Actual filled quantity: {
- exitOrderTicket.QuantityFilled}");
+ throw new RegressionTestException($@"Exit order ticket quantity and filled quantity do not match expected quantity for leg {i}. Expected: {expectedExitQuantity}. Actual quantity: {exitOrderTicket.Quantity}. Actual filled quantity: {exitOrderTicket.QuantityFilled}");
}
}
}
@@ -214,10 +211,10 @@ private decimal GetComboOrderFillPrice(List orderTickets)
{"Treynor Ratio", "0"},
{"Total Fees", "$36.00"},
{"Estimated Strategy Capacity", "$15000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZERHAT67A|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "2088.83%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "52947bba687287a189cee038daec6918"}
+ {"OrderListHash", "89a786ad77fd17f19037676d3fc66d94"}
};
}
}
diff --git a/Algorithm.CSharp/RollOutFrontMonthToBackMonthOptionUsingCalendarSpreadRegressionAlgorithm.cs b/Algorithm.CSharp/RollOutFrontMonthToBackMonthOptionUsingCalendarSpreadRegressionAlgorithm.cs
index 0ae067561412..ac4631d37454 100644
--- a/Algorithm.CSharp/RollOutFrontMonthToBackMonthOptionUsingCalendarSpreadRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/RollOutFrontMonthToBackMonthOptionUsingCalendarSpreadRegressionAlgorithm.cs
@@ -47,7 +47,7 @@ public override void Initialize()
SetCash(500000);
var option = AddOption("GOOG", Resolution.Minute);
- option.SetFilter(universe => universe.Strikes(-1, 1).Expiration(0, 62));
+ option.SetFilter(universe => universe.StandardsOnly().Strikes(-1, 1).Expiration(0, 62));
_symbol = option.Symbol;
}
@@ -178,10 +178,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "0"},
{"Total Fees", "$3.00"},
{"Estimated Strategy Capacity", "$190000.00"},
- {"Lowest Capacity Asset", "GOOCV 306CZK4DP0LC6|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 306CZK4DP4VNQ|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "1.19%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "007124f0e2e4f0048f367782ef7fcd02"}
+ {"OrderListHash", "860bacced1208f152cfc0aad369a111e"}
};
}
}
diff --git a/Algorithm.CSharp/SecurityInitializationOnReAdditionForEquityRegressionAlgorithm.cs b/Algorithm.CSharp/SecurityInitializationOnReAdditionForEquityRegressionAlgorithm.cs
index aa5ab9fe6138..193b76e2bb79 100644
--- a/Algorithm.CSharp/SecurityInitializationOnReAdditionForEquityRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/SecurityInitializationOnReAdditionForEquityRegressionAlgorithm.cs
@@ -187,12 +187,12 @@ protected virtual void AssertSecurityInitializationCount(Dictionary
/// Data Points count of all timeslices of algorithm
///
- public virtual long DataPoints => 4036;
+ public virtual long DataPoints => 4072;
///
/// Data Points count of the algorithm history
///
- public virtual int AlgorithmHistoryDataPoints => 3848;
+ public virtual int AlgorithmHistoryDataPoints => 2948;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/SecurityInitializationOnReAdditionForManuallyAddedFutureContractRegressionAlgorithm.cs b/Algorithm.CSharp/SecurityInitializationOnReAdditionForManuallyAddedFutureContractRegressionAlgorithm.cs
index 3546d5423298..fe86a481efbf 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 => 85;
+ public override long DataPoints => 101;
///
/// Data Points count of the algorithm history
///
- public override int AlgorithmHistoryDataPoints => 48;
+ public override int AlgorithmHistoryDataPoints => 80;
///
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
diff --git a/Algorithm.CSharp/SecurityInitializationOnReAdditionForManuallyAddedOptionRegressionAlgorithm.cs b/Algorithm.CSharp/SecurityInitializationOnReAdditionForManuallyAddedOptionRegressionAlgorithm.cs
index 61765e123bd5..efee84720b72 100644
--- a/Algorithm.CSharp/SecurityInitializationOnReAdditionForManuallyAddedOptionRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/SecurityInitializationOnReAdditionForManuallyAddedOptionRegressionAlgorithm.cs
@@ -83,7 +83,7 @@ protected override void AssertSecurityInitializationCount(Dictionary
/// Data Points count of all timeslices of algorithm
///
- public override long DataPoints => 115;
+ public override long DataPoints => 139;
///
/// Data Points count of the algorithm history
diff --git a/Algorithm.CSharp/SecuritySessionWithChangeOfResolutionRegressionAlgorithm.cs b/Algorithm.CSharp/SecuritySessionWithChangeOfResolutionRegressionAlgorithm.cs
index c484e18df742..00773ce5fd4e 100644
--- a/Algorithm.CSharp/SecuritySessionWithChangeOfResolutionRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/SecuritySessionWithChangeOfResolutionRegressionAlgorithm.cs
@@ -55,7 +55,7 @@ public override void OnEndOfDay(Symbol symbol)
///
/// Data Points count of all timeslices of algorithm
///
- public override long DataPoints => 3170;
+ public override long DataPoints => 3172;
///
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
diff --git a/Algorithm.CSharp/SecuritySessionWithFutureContractRegressionAlgorithm.cs b/Algorithm.CSharp/SecuritySessionWithFutureContractRegressionAlgorithm.cs
index b55bd7f46687..ea952a6b4d7d 100644
--- a/Algorithm.CSharp/SecuritySessionWithFutureContractRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/SecuritySessionWithFutureContractRegressionAlgorithm.cs
@@ -36,7 +36,7 @@ public override void InitializeSecurity()
SetEndDate(2013, 10, 08);
Security = AddFuture(Futures.Metals.Gold, Resolution.Minute, extendedMarketHours: ExtendedMarketHours);
- _futureContract = AddFutureContract(FuturesChain(Security.Symbol).First());
+ _futureContract = AddFutureContract(FuturesChain(Security.Symbol).OrderBy(x => x.Symbol.ID.Date).First());
// Manually add consolidators to simulate Session behavior
_continuousContractConsolidator = new MarketHourAwareConsolidator(false, Resolution.Daily, typeof(QuoteBar), TickType.Quote, false);
diff --git a/Algorithm.CSharp/SetAccountCurrencyCashBuyingPowerModelRegressionAlgorithm.cs b/Algorithm.CSharp/SetAccountCurrencyCashBuyingPowerModelRegressionAlgorithm.cs
index 9210b5a0ff33..0f1c623141ed 100644
--- a/Algorithm.CSharp/SetAccountCurrencyCashBuyingPowerModelRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/SetAccountCurrencyCashBuyingPowerModelRegressionAlgorithm.cs
@@ -239,7 +239,7 @@ public override void OnOrderEvent(OrderEvent orderEvent)
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 120;
+ public int AlgorithmHistoryDataPoints => 15;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/SetAccountCurrencySecurityMarginModelRegressionAlgorithm.cs b/Algorithm.CSharp/SetAccountCurrencySecurityMarginModelRegressionAlgorithm.cs
index a07fef771bfe..860ec82a273e 100644
--- a/Algorithm.CSharp/SetAccountCurrencySecurityMarginModelRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/SetAccountCurrencySecurityMarginModelRegressionAlgorithm.cs
@@ -198,7 +198,7 @@ public override void OnOrderEvent(OrderEvent orderEvent)
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 60;
+ public int AlgorithmHistoryDataPoints => 5;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/SingleOptionPositionGroupBuyingPowerModelRegressionAlgorithm.cs b/Algorithm.CSharp/SingleOptionPositionGroupBuyingPowerModelRegressionAlgorithm.cs
index ce8a9afbb5ab..9a58bcf25e16 100644
--- a/Algorithm.CSharp/SingleOptionPositionGroupBuyingPowerModelRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/SingleOptionPositionGroupBuyingPowerModelRegressionAlgorithm.cs
@@ -44,7 +44,7 @@ public override void Initialize()
var option = AddOption(equitySymbol);
_optionSymbol = option.Symbol;
- option.SetFilter(u => u.Strikes(-2, +2).Expiration(0, 180));
+ option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2).Expiration(0, 180));
}
public override void OnData(Slice slice)
@@ -124,8 +124,7 @@ private void PerfomQuantityCalculations(IPositionGroup positionGroup, Security s
if (positionQuantityForDeltaWithPositionGroupBuyingPowerModel != expectedQuantity)
{
- throw new RegressionTestException($@"Expected position quantity for delta buying power to be {expectedQuantity} but was {
- positionQuantityForDeltaWithPositionGroupBuyingPowerModel}");
+ throw new RegressionTestException($@"Expected position quantity for delta buying power to be {expectedQuantity} but was {positionQuantityForDeltaWithPositionGroupBuyingPowerModel}");
}
var position = positionGroup.Positions.Single();
@@ -144,8 +143,7 @@ private void PerfomQuantityCalculations(IPositionGroup positionGroup, Security s
if (positionQuantityForDeltaWithSecurityPositionGroupBuyingPowerModel != expectedSingleSecurityModelsQuantity ||
positionQuantityForDeltaWithSecurityBuyingPowerModel != expectedSingleSecurityModelsQuantity)
{
- throw new RegressionTestException($@"Expected order quantity for delta buying power calls from default buying power models to return {
- expectedSingleSecurityModelsQuantity}. Results were:" +
+ throw new RegressionTestException($@"Expected order quantity for delta buying power calls from default buying power models to return {expectedSingleSecurityModelsQuantity}. Results were:" +
$" \nSecurityPositionGroupBuyingPowerModel: {positionQuantityForDeltaWithSecurityPositionGroupBuyingPowerModel}" +
$" \nBuyingPowerModel: {positionQuantityForDeltaWithSecurityBuyingPowerModel}\n");
}
@@ -205,10 +203,10 @@ private void PerfomQuantityCalculations(IPositionGroup positionGroup, Security s
{"Treynor Ratio", "-4.737"},
{"Total Fees", "$19.50"},
{"Estimated Strategy Capacity", "$49000.00"},
- {"Lowest Capacity Asset", "GOOCV W78ZFMML01JA|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV W78ZFMML4BUU|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "0.45%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "5d2df7cb88dbc63da13518c0195eea60"}
+ {"OrderListHash", "8b8bafd11c0c2a868dbbc28db36d4ce0"}
};
}
}
diff --git a/Algorithm.CSharp/StartingCapitalRegressionAlgorithm.cs b/Algorithm.CSharp/StartingCapitalRegressionAlgorithm.cs
index 0b6e2bafeff9..de6681e61c76 100644
--- a/Algorithm.CSharp/StartingCapitalRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/StartingCapitalRegressionAlgorithm.cs
@@ -77,7 +77,7 @@ public override void OnData(Slice slice)
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 180;
+ public int AlgorithmHistoryDataPoints => 25;
///
/// Final status of the algorithm
@@ -95,7 +95,7 @@ public override void OnData(Slice slice)
{"Compounding Annual Return", "0%"},
{"Drawdown", "0%"},
{"Expectancy", "0"},
- {"Start Equity", "76970482.10"},
+ {"Start Equity", "77011732.10"},
{"End Equity", "71490762.61"},
{"Net Profit", "0%"},
{"Sharpe Ratio", "0"},
diff --git a/Algorithm.CSharp/SwitchDataModeRegressionAlgorithm.cs b/Algorithm.CSharp/SwitchDataModeRegressionAlgorithm.cs
index f609455b1441..8028d79d1642 100644
--- a/Algorithm.CSharp/SwitchDataModeRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/SwitchDataModeRegressionAlgorithm.cs
@@ -54,7 +54,8 @@ public override void OnData(Slice slice)
{
if (Time.Hour == 9 && Time.Minute == 58)
{
- AddOption(UnderlyingTicker);
+ var option = AddOption(UnderlyingTicker);
+ option.SetFilter(u => u.StandardsOnly().Strikes(-1, 1).Expiration(0, 35));
}
AssertValue(slice);
diff --git a/Algorithm.CSharp/TwoLegCurrencyConversionRegressionAlgorithm.cs b/Algorithm.CSharp/TwoLegCurrencyConversionRegressionAlgorithm.cs
index ec6492821a38..cad8d5c8a156 100644
--- a/Algorithm.CSharp/TwoLegCurrencyConversionRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/TwoLegCurrencyConversionRegressionAlgorithm.cs
@@ -111,7 +111,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 120;
+ public int AlgorithmHistoryDataPoints => 20;
///
/// Final status of the algorithm
@@ -129,7 +129,7 @@ public override void OnEndOfAlgorithm()
{"Compounding Annual Return", "0%"},
{"Drawdown", "0%"},
{"Expectancy", "0"},
- {"Start Equity", "132348.63"},
+ {"Start Equity", "132337.76"},
{"End Equity", "131620.05"},
{"Net Profit", "0%"},
{"Sharpe Ratio", "0"},
diff --git a/Algorithm.CSharp/UniverseSelectionSymbolCacheRemovalRegressionTest.cs b/Algorithm.CSharp/UniverseSelectionSymbolCacheRemovalRegressionTest.cs
index 3f218de4e2a6..aff4c7fb7d1c 100644
--- a/Algorithm.CSharp/UniverseSelectionSymbolCacheRemovalRegressionTest.cs
+++ b/Algorithm.CSharp/UniverseSelectionSymbolCacheRemovalRegressionTest.cs
@@ -100,7 +100,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 24288;
+ public long DataPoints => 24289;
///
/// Data Points count of the algorithm history
diff --git a/Algorithm.CSharp/UniverseSharingSecurityDifferentSubscriptionRequestRegressionAlgorithm.cs b/Algorithm.CSharp/UniverseSharingSecurityDifferentSubscriptionRequestRegressionAlgorithm.cs
index 08255b804a7a..fd243770ccfe 100644
--- a/Algorithm.CSharp/UniverseSharingSecurityDifferentSubscriptionRequestRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/UniverseSharingSecurityDifferentSubscriptionRequestRegressionAlgorithm.cs
@@ -134,7 +134,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 7000;
+ public long DataPoints => 7001;
///
/// Data Points count of the algorithm history
diff --git a/Algorithm.CSharp/UniverseSharingSubscriptionTradableRegressionAlgorithm.cs b/Algorithm.CSharp/UniverseSharingSubscriptionTradableRegressionAlgorithm.cs
index 3c7e89deb603..510a26f91332 100644
--- a/Algorithm.CSharp/UniverseSharingSubscriptionTradableRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/UniverseSharingSubscriptionTradableRegressionAlgorithm.cs
@@ -114,7 +114,7 @@ public override void OnSecuritiesChanged(SecurityChanges changes)
///
/// Data Points count of all timeslices of algorithm
///
- public long DataPoints => 228;
+ public long DataPoints => 229;
///
/// Data Points count of the algorithm history
diff --git a/Algorithm.CSharp/UnsettledCashWhenQuoteCurrencyIsNotAccountCurrencyAlgorithm.cs b/Algorithm.CSharp/UnsettledCashWhenQuoteCurrencyIsNotAccountCurrencyAlgorithm.cs
index 858bcd24f6d8..2bb42245d952 100644
--- a/Algorithm.CSharp/UnsettledCashWhenQuoteCurrencyIsNotAccountCurrencyAlgorithm.cs
+++ b/Algorithm.CSharp/UnsettledCashWhenQuoteCurrencyIsNotAccountCurrencyAlgorithm.cs
@@ -169,7 +169,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 7594;
+ public int AlgorithmHistoryDataPoints => 50;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/WarmupConversionRatesRegressionAlgorithm.cs b/Algorithm.CSharp/WarmupConversionRatesRegressionAlgorithm.cs
index 96c1b0fb5cd1..9c96947d10d8 100644
--- a/Algorithm.CSharp/WarmupConversionRatesRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/WarmupConversionRatesRegressionAlgorithm.cs
@@ -86,7 +86,7 @@ public override void OnData(Slice slice)
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 180;
+ public int AlgorithmHistoryDataPoints => 20;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/WarmupDataTypesBarCountWarmupRegressionAlgorithm.cs b/Algorithm.CSharp/WarmupDataTypesBarCountWarmupRegressionAlgorithm.cs
index 0cc28198afd6..2249add732c9 100644
--- a/Algorithm.CSharp/WarmupDataTypesBarCountWarmupRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/WarmupDataTypesBarCountWarmupRegressionAlgorithm.cs
@@ -33,6 +33,6 @@ public override void Initialize()
///
/// Data Points count of all timeslices of algorithm
///
- public override long DataPoints => 5298;
+ public override long DataPoints => 5299;
}
}
diff --git a/Algorithm.CSharp/WarmupDataTypesRegressionAlgorithm.cs b/Algorithm.CSharp/WarmupDataTypesRegressionAlgorithm.cs
index b00eec8b0849..db08422c87f9 100644
--- a/Algorithm.CSharp/WarmupDataTypesRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/WarmupDataTypesRegressionAlgorithm.cs
@@ -99,12 +99,12 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of all timeslices of algorithm
///
- public virtual long DataPoints => 3763;
+ public virtual long DataPoints => 3764;
///
/// Data Points count of the algorithm history
///
- public virtual int AlgorithmHistoryDataPoints => 41;
+ public virtual int AlgorithmHistoryDataPoints => 5;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/WarmupLowerResolutionOptionRegressionAlgorithm.cs b/Algorithm.CSharp/WarmupLowerResolutionOptionRegressionAlgorithm.cs
index 266ba4b4d371..764fedd6a9eb 100644
--- a/Algorithm.CSharp/WarmupLowerResolutionOptionRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/WarmupLowerResolutionOptionRegressionAlgorithm.cs
@@ -167,10 +167,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "0"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$5000.00"},
- {"Lowest Capacity Asset", "AAPL 2ZTXYMUME0LUU|AAPL R735QTJ8XC9X"},
+ {"Lowest Capacity Asset", "AAPL 2ZTXYMUME4W6E|AAPL R735QTJ8XC9X"},
{"Portfolio Turnover", "1.08%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "1dfc2281fd254870f2e32528e7bb7842"}
+ {"OrderListHash", "94523a9f34b004d45970aa5ed06f8672"}
};
}
}
diff --git a/Algorithm.CSharp/WarmupOptionRegressionAlgorithm.cs b/Algorithm.CSharp/WarmupOptionRegressionAlgorithm.cs
index af40df66beb9..0490920a8664 100644
--- a/Algorithm.CSharp/WarmupOptionRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/WarmupOptionRegressionAlgorithm.cs
@@ -154,10 +154,10 @@ public override void OnEndOfAlgorithm()
{"Treynor Ratio", "0"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$1300000.00"},
- {"Lowest Capacity Asset", "GOOCV 30AKMEIPOSS1Y|GOOCV VP83T1ZUHROL"},
+ {"Lowest Capacity Asset", "GOOCV 30AKMEIPOX2DI|GOOCV VP83T1ZUHROL"},
{"Portfolio Turnover", "10.71%"},
{"Drawdown Recovery", "0"},
- {"OrderListHash", "8a36462ee0349c04d01d464e592dd347"}
+ {"OrderListHash", "19ba1220073493495880581b38df2da9"}
};
}
}
diff --git a/Algorithm.CSharp/WarmupTrainRegressionAlgorithm.cs b/Algorithm.CSharp/WarmupTrainRegressionAlgorithm.cs
index f5a8a55f05b0..584b04234ae9 100644
--- a/Algorithm.CSharp/WarmupTrainRegressionAlgorithm.cs
+++ b/Algorithm.CSharp/WarmupTrainRegressionAlgorithm.cs
@@ -73,7 +73,7 @@ public override void OnEndOfAlgorithm()
///
/// Data Points count of the algorithm history
///
- public int AlgorithmHistoryDataPoints => 7494;
+ public int AlgorithmHistoryDataPoints => 48;
///
/// Final status of the algorithm
diff --git a/Algorithm.CSharp/YearlyUniverseSelectionScheduleRegressionAlgorithm.cs b/Algorithm.CSharp/YearlyUniverseSelectionScheduleRegressionAlgorithm.cs
new file mode 100644
index 000000000000..0570b76fda4f
--- /dev/null
+++ b/Algorithm.CSharp/YearlyUniverseSelectionScheduleRegressionAlgorithm.cs
@@ -0,0 +1,135 @@
+/*
+ * 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 QuantConnect.Data;
+using QuantConnect.Interfaces;
+using System.Collections.Generic;
+using QuantConnect.Data.Fundamental;
+using QuantConnect.Data.UniverseSelection;
+
+namespace QuantConnect.Algorithm.CSharp
+{
+ ///
+ /// Regression test algorithm for scheduled universe selection GH 3890
+ ///
+ public class YearlyUniverseSelectionScheduleRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
+ {
+ private int _yearlyDateSelection;
+ private readonly Symbol _symbol = QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA);
+
+ ///
+ /// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
+ ///
+ public override void Initialize()
+ {
+ SetStartDate(2014, 03, 25);
+ SetEndDate(2014, 05, 10);
+ UniverseSettings.Resolution = Resolution.Daily;
+
+ AddUniverse(DateRules.YearStart(), SelectionFunction);
+ }
+
+ public IEnumerable SelectionFunction(IEnumerable coarse)
+ {
+ _yearlyDateSelection++;
+ if (Time != StartDate)
+ {
+ throw new RegressionTestException($"SelectionFunction_SpecificDate unexpected selection: {Time}");
+ }
+ return new[] { _symbol };
+ }
+
+ ///
+ /// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
+ ///
+ /// Slice object keyed by symbol containing the stock data
+ public override void OnData(Slice slice)
+ {
+ if (!Portfolio.Invested)
+ {
+ SetHoldings(_symbol, 1);
+ Debug($"Purchased Stock {_symbol}");
+ }
+ }
+
+ public override void OnEndOfAlgorithm()
+ {
+ if (_yearlyDateSelection != 1)
+ {
+ throw new RegressionTestException($"Initial yearly selection didn't happen!");
+ }
+ }
+
+ ///
+ /// Data Points count of all timeslices of algorithm
+ ///
+ public long DataPoints => 271;
+
+ ///
+ /// 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 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 };
+
+ ///
+ /// 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", "1"},
+ {"Average Win", "0%"},
+ {"Average Loss", "0%"},
+ {"Compounding Annual Return", "4.334%"},
+ {"Drawdown", "3.900%"},
+ {"Expectancy", "0"},
+ {"Start Equity", "100000"},
+ {"End Equity", "100532.22"},
+ {"Net Profit", "0.532%"},
+ {"Sharpe Ratio", "0.28"},
+ {"Sortino Ratio", "0.283"},
+ {"Probabilistic Sharpe Ratio", "39.422%"},
+ {"Loss Rate", "0%"},
+ {"Win Rate", "0%"},
+ {"Profit-Loss Ratio", "0"},
+ {"Alpha", "-0.022"},
+ {"Beta", "1.018"},
+ {"Annual Standard Deviation", "0.099"},
+ {"Annual Variance", "0.01"},
+ {"Information Ratio", "-2.462"},
+ {"Tracking Error", "0.009"},
+ {"Treynor Ratio", "0.027"},
+ {"Total Fees", "$3.07"},
+ {"Estimated Strategy Capacity", "$920000000.00"},
+ {"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
+ {"Portfolio Turnover", "2.20%"},
+ {"Drawdown Recovery", "5"},
+ {"OrderListHash", "87438e51988f37757a2d7f97389483ea"}
+ };
+ }
+}
diff --git a/Algorithm.Framework/Alphas/BasePairsTradingAlphaModel.cs b/Algorithm.Framework/Alphas/BasePairsTradingAlphaModel.cs
index d9c1f9c60e0d..b4a7aa1d484c 100644
--- a/Algorithm.Framework/Alphas/BasePairsTradingAlphaModel.cs
+++ b/Algorithm.Framework/Alphas/BasePairsTradingAlphaModel.cs
@@ -117,7 +117,16 @@ public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges
/// The first asset's symbol in the pair
/// The second asset's symbol in the pair
/// True if the statistical test for the pair is successful
- public virtual bool HasPassedTest(QCAlgorithm algorithm, Symbol asset1, Symbol asset2) => true;
+ public virtual bool HasPassedTest(QCAlgorithm algorithm, Symbol asset1, Symbol asset2)
+ {
+ // Check if this method was overridden in Python
+ if (TryInvokePythonOverride(nameof(HasPassedTest), out bool result, algorithm, asset1, asset2))
+ {
+ return result;
+ }
+
+ return true;
+ }
private void UpdatePairs(QCAlgorithm algorithm)
{
diff --git a/Algorithm.Framework/Alphas/ConstantAlphaModel.cs b/Algorithm.Framework/Alphas/ConstantAlphaModel.cs
index ca0c190a5487..4aaa302e10f8 100644
--- a/Algorithm.Framework/Alphas/ConstantAlphaModel.cs
+++ b/Algorithm.Framework/Alphas/ConstantAlphaModel.cs
@@ -36,17 +36,6 @@ public class ConstantAlphaModel : AlphaModel
private readonly HashSet _securities;
private readonly Dictionary _insightsTimeBySymbol;
- ///
- /// Initializes a new instance of the class
- ///
- /// The type of insight
- /// The direction of the insight
- /// The period over which the insight with come to fruition
- public ConstantAlphaModel(InsightType type, InsightDirection direction, TimeSpan period)
- : this(type, direction, period, null, null)
- {
- }
-
///
/// Initializes a new instance of the class
///
@@ -56,7 +45,7 @@ public ConstantAlphaModel(InsightType type, InsightDirection direction, TimeSpan
/// The predicted change in magnitude as a +- percentage
/// The confidence in the insight
/// The portfolio weight of the insights
- public ConstantAlphaModel(InsightType type, InsightDirection direction, TimeSpan period, double? magnitude, double? confidence, double? weight = null)
+ public ConstantAlphaModel(InsightType type, InsightDirection direction, TimeSpan period, double? magnitude = null, double? confidence = null, double? weight = null)
{
_type = type;
_direction = direction;
@@ -127,7 +116,7 @@ public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges
/// The symbol to emit an insight for
protected virtual bool ShouldEmitInsight(DateTime utcTime, Symbol symbol)
{
- if(symbol.IsCanonical())
+ if (symbol.IsCanonical())
{
// canonical futures & options are none tradable
return false;
diff --git a/Algorithm.Framework/Alphas/PearsonCorrelationPairsTradingAlphaModel.cs b/Algorithm.Framework/Alphas/PearsonCorrelationPairsTradingAlphaModel.cs
index ba39c197ef14..97a30441e3ff 100644
--- a/Algorithm.Framework/Alphas/PearsonCorrelationPairsTradingAlphaModel.cs
+++ b/Algorithm.Framework/Alphas/PearsonCorrelationPairsTradingAlphaModel.cs
@@ -1,4 +1,4 @@
-/*
+/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
@@ -92,6 +92,12 @@ public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges
/// True if the statistical test for the pair is successful
public override bool HasPassedTest(QCAlgorithm algorithm, Symbol asset1, Symbol asset2)
{
+ // Check if this method was overridden in Python
+ if (TryInvokePythonOverride(nameof(HasPassedTest), out bool result, algorithm, asset1, asset2))
+ {
+ return result;
+ }
+
return _bestPair != null && asset1 == _bestPair.Item1 && asset2 == _bestPair.Item2;
}
diff --git a/Algorithm.Framework/Execution/SpreadExecutionModel.cs b/Algorithm.Framework/Execution/SpreadExecutionModel.cs
index 3a612616e8cd..0d30fb89053e 100644
--- a/Algorithm.Framework/Execution/SpreadExecutionModel.cs
+++ b/Algorithm.Framework/Execution/SpreadExecutionModel.cs
@@ -83,6 +83,12 @@ public override void Execute(QCAlgorithm algorithm, IPortfolioTarget[] targets)
///
protected virtual bool PriceIsFavorable(Security security)
{
+ // Check if this method was overridden in Python
+ if (TryInvokePythonOverride(nameof(PriceIsFavorable), out bool result, security))
+ {
+ return result;
+ }
+
// Has to be in opening hours of exchange to avoid extreme spread in OTC period
// Price has to be larger than zero to avoid zero division error, or negative price causing the spread percentage lower than preset value by accident
return security.Exchange.ExchangeOpen
diff --git a/Algorithm.Framework/Execution/StandardDeviationExecutionModel.cs b/Algorithm.Framework/Execution/StandardDeviationExecutionModel.cs
index 75e42904fb7a..97f85f5bf547 100644
--- a/Algorithm.Framework/Execution/StandardDeviationExecutionModel.cs
+++ b/Algorithm.Framework/Execution/StandardDeviationExecutionModel.cs
@@ -147,6 +147,12 @@ public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges
///
protected virtual bool PriceIsFavorable(SymbolData data, decimal unorderedQuantity)
{
+ // Check if this method was overridden in Python
+ if (TryInvokePythonOverride(nameof(PriceIsFavorable), out bool result, data, unorderedQuantity))
+ {
+ return result;
+ }
+
var deviations = _deviations * data.STD;
return unorderedQuantity > 0
? data.Security.BidPrice < data.SMA - deviations
@@ -158,6 +164,12 @@ protected virtual bool PriceIsFavorable(SymbolData data, decimal unorderedQuanti
///
protected virtual bool IsSafeToRemove(QCAlgorithm algorithm, Symbol symbol)
{
+ // Check if this method was overridden in Python
+ if (TryInvokePythonOverride(nameof(IsSafeToRemove), out bool result, algorithm, symbol))
+ {
+ return result;
+ }
+
// confirm the security isn't currently a member of any universe
return !algorithm.UniverseManager.Any(kvp => kvp.Value.ContainsMember(symbol));
}
diff --git a/Algorithm.Framework/Execution/VolumeWeightedAveragePriceExecutionModel.cs b/Algorithm.Framework/Execution/VolumeWeightedAveragePriceExecutionModel.cs
index 45b066d2a8f1..7cb385bac893 100644
--- a/Algorithm.Framework/Execution/VolumeWeightedAveragePriceExecutionModel.cs
+++ b/Algorithm.Framework/Execution/VolumeWeightedAveragePriceExecutionModel.cs
@@ -131,6 +131,12 @@ public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges
///
protected virtual bool IsSafeToRemove(QCAlgorithm algorithm, Symbol symbol)
{
+ // Check if this method was overridden in Python
+ if (TryInvokePythonOverride(nameof(IsSafeToRemove), out bool result, algorithm, symbol))
+ {
+ return result;
+ }
+
// confirm the security isn't currently a member of any universe
return !algorithm.UniverseManager.Any(kvp => kvp.Value.ContainsMember(symbol));
}
@@ -140,6 +146,12 @@ protected virtual bool IsSafeToRemove(QCAlgorithm algorithm, Symbol symbol)
///
protected virtual bool PriceIsFavorable(SymbolData data, decimal unorderedQuantity)
{
+ // Check if this method was overridden in Python
+ if (TryInvokePythonOverride(nameof(PriceIsFavorable), out bool result, data, unorderedQuantity))
+ {
+ return result;
+ }
+
if (unorderedQuantity > 0)
{
if (data.Security.BidPrice < data.VWAP)
@@ -188,7 +200,7 @@ public SymbolData(QCAlgorithm algorithm, Security security)
var name = algorithm.CreateIndicatorName(security.Symbol, "VWAP", security.Resolution);
VWAP = new IntradayVwap(name);
- algorithm.RegisterIndicator(security.Symbol, VWAP, Consolidator, bd => (BaseData) bd);
+ algorithm.RegisterIndicator(security.Symbol, VWAP, Consolidator, bd => (BaseData)bd);
}
}
}
diff --git a/Algorithm.Framework/QuantConnect.Algorithm.Framework.csproj b/Algorithm.Framework/QuantConnect.Algorithm.Framework.csproj
index 46d7734a7ba2..1cd1d678d750 100644
--- a/Algorithm.Framework/QuantConnect.Algorithm.Framework.csproj
+++ b/Algorithm.Framework/QuantConnect.Algorithm.Framework.csproj
@@ -4,7 +4,7 @@
AnyCPU
QuantConnect.Algorithm.Framework
QuantConnect.Algorithm.Framework
- net9.0
+ net10.0
false
bin\$(Configuration)\
AllEnabledByDefault
@@ -29,7 +29,7 @@
LICENSE
-
+
diff --git a/Algorithm.Framework/Selection/CoarseFundamentalUniverseSelectionModel.cs b/Algorithm.Framework/Selection/CoarseFundamentalUniverseSelectionModel.cs
index 414336b03606..99373adcbcbb 100644
--- a/Algorithm.Framework/Selection/CoarseFundamentalUniverseSelectionModel.cs
+++ b/Algorithm.Framework/Selection/CoarseFundamentalUniverseSelectionModel.cs
@@ -17,7 +17,6 @@
using System.Collections.Generic;
using Python.Runtime;
using QuantConnect.Data.UniverseSelection;
-using QuantConnect.Securities;
namespace QuantConnect.Algorithm.Framework.Selection
{
@@ -61,6 +60,11 @@ public CoarseFundamentalUniverseSelectionModel(
///
public override IEnumerable SelectCoarse(QCAlgorithm algorithm, IEnumerable coarse)
{
+ // Check if this method was overridden in Python
+ if (TryInvokePythonOverride(nameof(SelectCoarse), out IEnumerable result, algorithm, coarse))
+ {
+ return result;
+ }
return _coarseSelector(coarse);
}
}
diff --git a/Algorithm.Framework/Selection/EmaCrossUniverseSelectionModel.cs b/Algorithm.Framework/Selection/EmaCrossUniverseSelectionModel.cs
index 774797f14379..5a1df09c201f 100644
--- a/Algorithm.Framework/Selection/EmaCrossUniverseSelectionModel.cs
+++ b/Algorithm.Framework/Selection/EmaCrossUniverseSelectionModel.cs
@@ -1,4 +1,4 @@
-/*
+/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
@@ -65,17 +65,23 @@ public EmaCrossUniverseSelectionModel(
/// An enumerable of symbols passing the filter
public override IEnumerable SelectCoarse(QCAlgorithm algorithm, IEnumerable coarse)
{
+ // Check if this method was overridden in Python
+ if (TryInvokePythonOverride(nameof(SelectCoarse), out IEnumerable result, algorithm, coarse))
+ {
+ return result;
+ }
+
return (from cf in coarse
// grab th SelectionData instance for this symbol
- let avg = _averages.GetOrAdd(cf.Symbol, sym => new SelectionData(_fastPeriod, _slowPeriod))
- // Update returns true when the indicators are ready, so don't accept until they are
- where avg.Update(cf.EndTime, cf.AdjustedPrice)
- // only pick symbols who have their _fastPeriod-day ema over their _slowPeriod-day ema
- where avg.Fast > avg.Slow * (1 + _tolerance)
- // prefer symbols with a larger delta by percentage between the two averages
- orderby avg.ScaledDelta descending
- // we only need to return the symbol and return 'Count' symbols
- select cf.Symbol).Take(_universeCount);
+ let avg = _averages.GetOrAdd(cf.Symbol, sym => new SelectionData(_fastPeriod, _slowPeriod))
+ // Update returns true when the indicators are ready, so don't accept until they are
+ where avg.Update(cf.EndTime, cf.AdjustedPrice)
+ // only pick symbols who have their _fastPeriod-day ema over their _slowPeriod-day ema
+ where avg.Fast > avg.Slow * (1 + _tolerance)
+ // prefer symbols with a larger delta by percentage between the two averages
+ orderby avg.ScaledDelta descending
+ // we only need to return the symbol and return 'Count' symbols
+ select cf.Symbol).Take(_universeCount);
}
// class used to improve readability of the coarse selection function
@@ -97,4 +103,4 @@ public SelectionData(int fastPeriod, int slowPeriod)
public bool Update(DateTime time, decimal value) => Fast.Update(time, value) & Slow.Update(time, value);
}
}
-}
\ No newline at end of file
+}
diff --git a/Algorithm.Framework/Selection/FineFundamentalUniverseSelectionModel.cs b/Algorithm.Framework/Selection/FineFundamentalUniverseSelectionModel.cs
index e5f549808643..c209b1e884d4 100644
--- a/Algorithm.Framework/Selection/FineFundamentalUniverseSelectionModel.cs
+++ b/Algorithm.Framework/Selection/FineFundamentalUniverseSelectionModel.cs
@@ -71,12 +71,24 @@ public FineFundamentalUniverseSelectionModel(
///
public override IEnumerable SelectCoarse(QCAlgorithm algorithm, IEnumerable coarse)
{
+ // Check if this method was overridden in Python
+ if (TryInvokePythonOverride(nameof(SelectCoarse), out IEnumerable result, algorithm, coarse))
+ {
+ return result;
+ }
+
return _coarseSelector(coarse);
}
///
public override IEnumerable SelectFine(QCAlgorithm algorithm, IEnumerable fine)
{
+ // Check if this method was overridden in Python
+ if (TryInvokePythonOverride(nameof(SelectFine), out IEnumerable result, algorithm, fine))
+ {
+ return result;
+ }
+
return _fineSelector(fine);
}
}
diff --git a/Algorithm.Framework/Selection/FundamentalUniverseSelectionModel.cs b/Algorithm.Framework/Selection/FundamentalUniverseSelectionModel.cs
index 710898d9d9db..1ba078e51a64 100644
--- a/Algorithm.Framework/Selection/FundamentalUniverseSelectionModel.cs
+++ b/Algorithm.Framework/Selection/FundamentalUniverseSelectionModel.cs
@@ -175,6 +175,12 @@ public override IEnumerable CreateUniverses(QCAlgorithm algorithm)
/// The coarse fundamental universe
public virtual Universe CreateCoarseFundamentalUniverse(QCAlgorithm algorithm)
{
+ // Check if this method was overridden in Python
+ if (TryInvokePythonOverride(nameof(CreateCoarseFundamentalUniverse), out Universe result, algorithm))
+ {
+ return result;
+ }
+
var universeSettings = _universeSettings ?? algorithm.UniverseSettings;
return new CoarseFundamentalUniverse(universeSettings, coarse =>
{
@@ -198,9 +204,15 @@ public virtual Universe CreateCoarseFundamentalUniverse(QCAlgorithm algorithm)
/// An enumerable of symbols passing the filter
public virtual IEnumerable Select(QCAlgorithm algorithm, IEnumerable fundamental)
{
- if(_selector == null)
+ // Check if this method was overridden in Python
+ if (TryInvokePythonOverride(nameof(Select), out IEnumerable result, algorithm, fundamental))
+ {
+ return result;
+ }
+
+ if (_selector == null)
{
- throw new NotImplementedException("If inheriting, please overrride the 'Select' fundamental function, else provide it as a constructor parameter");
+ throw new NotImplementedException("If inheriting, please override the 'Select' fundamental function, else provide it as a constructor parameter");
}
return _selector(fundamental);
}
@@ -214,7 +226,13 @@ public virtual IEnumerable Select(QCAlgorithm algorithm, IEnumerable)'")]
public virtual IEnumerable SelectCoarse(QCAlgorithm algorithm, IEnumerable coarse)
{
- throw new NotImplementedException("Please overrride the 'Select' fundamental function");
+ // Check if this method was overridden in Python
+ if (TryInvokePythonOverride(nameof(SelectCoarse), out IEnumerable result, algorithm, coarse))
+ {
+ return result;
+ }
+
+ throw new NotImplementedException("Please override the 'Select' fundamental function");
}
///
@@ -226,6 +244,12 @@ public virtual IEnumerable SelectCoarse(QCAlgorithm algorithm, IEnumerab
[Obsolete("Fine and Coarse selection are merged, please use 'Select(QCAlgorithm, IEnumerable)'")]
public virtual IEnumerable SelectFine(QCAlgorithm algorithm, IEnumerable fine)
{
+ // Check if this method was overridden in Python
+ if (TryInvokePythonOverride(nameof(SelectFine), out IEnumerable result, algorithm, fine))
+ {
+ return result;
+ }
+
// default impl performs no filtering of fine data
return fine.Select(f => f.Symbol);
}
diff --git a/Algorithm.Framework/Selection/FundamentalUniverseSelectionModel.py b/Algorithm.Framework/Selection/FundamentalUniverseSelectionModel.py
index daa9ac734346..47ba76f32071 100644
--- a/Algorithm.Framework/Selection/FundamentalUniverseSelectionModel.py
+++ b/Algorithm.Framework/Selection/FundamentalUniverseSelectionModel.py
@@ -17,19 +17,19 @@ class FundamentalUniverseSelectionModel:
'''Provides a base class for defining equity coarse/fine fundamental selection models'''
def __init__(self,
- filterFineData = None,
- universeSettings = None):
+ filter_fine_data = None,
+ universe_settings = None):
'''Initializes a new instance of the FundamentalUniverseSelectionModel class
Args:
- filterFineData: [Obsolete] Fine and Coarse selection are merged
- universeSettings: The settings used when adding symbols to the algorithm, specify null to use algorithm.UniverseSettings'''
- self.filter_fine_data = filterFineData
+ filter_fine_data: [Obsolete] Fine and Coarse selection are merged
+ universeSettings: The settings used when adding symbols to the algorithm, specify null to use algorithm.universe_settings'''
+ self.filter_fine_data = filter_fine_data
if self.filter_fine_data == None:
self.fundamental_data = True
else:
self.fundamental_data = False
self.market = Market.USA
- self.universe_settings = universeSettings
+ self.universe_settings = universe_settings
def create_universes(self, algorithm: QCAlgorithm) -> list[Universe]:
diff --git a/Algorithm.Framework/Selection/FutureUniverseSelectionModel.cs b/Algorithm.Framework/Selection/FutureUniverseSelectionModel.cs
index 23851199e6cc..fb9c35e141e3 100644
--- a/Algorithm.Framework/Selection/FutureUniverseSelectionModel.cs
+++ b/Algorithm.Framework/Selection/FutureUniverseSelectionModel.cs
@@ -28,7 +28,6 @@ namespace QuantConnect.Algorithm.Framework.Selection
public class FutureUniverseSelectionModel : UniverseSelectionModel
{
private DateTime _nextRefreshTimeUtc;
-
private readonly TimeSpan _refreshInterval;
private readonly UniverseSettings _universeSettings;
private readonly Func> _futureChainSymbolSelector;
@@ -121,6 +120,11 @@ public override IEnumerable CreateUniverses(QCAlgorithm algorithm)
///
protected virtual FutureFilterUniverse Filter(FutureFilterUniverse filter)
{
+ // Check if this method was overridden in Python
+ if (TryInvokePythonOverride(nameof(Filter), out FutureFilterUniverse result, filter))
+ {
+ return result;
+ }
// NOP
return filter;
}
diff --git a/Algorithm.Framework/Selection/InceptionDateUniverseSelectionModel.cs b/Algorithm.Framework/Selection/InceptionDateUniverseSelectionModel.cs
index f31aba87d7ce..f46cccb77c32 100644
--- a/Algorithm.Framework/Selection/InceptionDateUniverseSelectionModel.cs
+++ b/Algorithm.Framework/Selection/InceptionDateUniverseSelectionModel.cs
@@ -16,7 +16,6 @@
using QuantConnect.Data.UniverseSelection;
using System;
using System.Collections.Generic;
-using System.Linq;
using Python.Runtime;
namespace QuantConnect.Algorithm.Framework.Selection
@@ -36,7 +35,7 @@ public class InceptionDateUniverseSelectionModel : CustomUniverseSelectionModel
/// A unique name for this universe
/// Dictionary of DateTime keyed by String that represent the Inception date for each ticker
public InceptionDateUniverseSelectionModel(string name, Dictionary tickersByDate) :
- base(name, (Func>) null)
+ base(name, (Func>)null)
{
_queue = new Queue>(tickersByDate);
_symbols = new List();
@@ -57,6 +56,12 @@ public InceptionDateUniverseSelectionModel(string name, PyObject tickersByDate)
///
public override IEnumerable Select(QCAlgorithm algorithm, DateTime date)
{
+ // Check if this method was overridden in Python
+ if (TryInvokePythonOverride(nameof(Select), out IEnumerable result, algorithm, date))
+ {
+ return result;
+ }
+
// Move Symbols that are trading from the queue to a list
var added = new List();
while (_queue.TryPeek(out var keyValuePair) && keyValuePair.Value <= date)
diff --git a/Algorithm.Framework/Selection/OpenInterestFutureUniverseSelectionModel.cs b/Algorithm.Framework/Selection/OpenInterestFutureUniverseSelectionModel.cs
index 6726fc304eca..952c83f31e04 100644
--- a/Algorithm.Framework/Selection/OpenInterestFutureUniverseSelectionModel.cs
+++ b/Algorithm.Framework/Selection/OpenInterestFutureUniverseSelectionModel.cs
@@ -74,6 +74,12 @@ public OpenInterestFutureUniverseSelectionModel(IAlgorithm algorithm, PyObject f
///
protected override FutureFilterUniverse Filter(FutureFilterUniverse filter)
{
+ // Check if this method was overridden in Python
+ if (TryInvokePythonOverride(nameof(Filter), out FutureFilterUniverse result, filter))
+ {
+ return result;
+ }
+
// Remove duplicated keys
return filter.Contracts(FilterByOpenInterest(
filter.DistinctBy(x => x).ToDictionary(x => x.Symbol, x => _marketHoursDatabase.GetEntry(x.ID.Market, x, x.ID.SecurityType))));
diff --git a/Algorithm.Framework/Selection/OptionUniverseSelectionModel.cs b/Algorithm.Framework/Selection/OptionUniverseSelectionModel.cs
index e832e5e3261e..3c78638f3e74 100644
--- a/Algorithm.Framework/Selection/OptionUniverseSelectionModel.cs
+++ b/Algorithm.Framework/Selection/OptionUniverseSelectionModel.cs
@@ -28,7 +28,6 @@ namespace QuantConnect.Algorithm.Framework.Selection
public class OptionUniverseSelectionModel : UniverseSelectionModel
{
private DateTime _nextRefreshTimeUtc;
-
private readonly TimeSpan _refreshInterval;
private readonly UniverseSettings _universeSettings;
private readonly Func> _optionChainSymbolSelector;
@@ -118,6 +117,12 @@ public override IEnumerable CreateUniverses(QCAlgorithm algorithm)
///
protected virtual OptionFilterUniverse Filter(OptionFilterUniverse filter)
{
+ // Check if this method was overridden in Python
+ if (TryInvokePythonOverride(nameof(Filter), out OptionFilterUniverse result, filter))
+ {
+ return result;
+ }
+
// NOP
return filter;
}
diff --git a/Algorithm.Framework/Selection/QC500UniverseSelectionModel.cs b/Algorithm.Framework/Selection/QC500UniverseSelectionModel.cs
index 08c8f2df75dd..946fe0018ffa 100644
--- a/Algorithm.Framework/Selection/QC500UniverseSelectionModel.cs
+++ b/Algorithm.Framework/Selection/QC500UniverseSelectionModel.cs
@@ -33,7 +33,7 @@ public class QC500UniverseSelectionModel : FundamentalUniverseSelectionModel
// rebalances at the start of each month
private int _lastMonth = -1;
- private readonly Dictionary _dollarVolumeBySymbol = new ();
+ private readonly Dictionary _dollarVolumeBySymbol = new();
///
/// Initializes a new default instance of the
@@ -60,6 +60,12 @@ public QC500UniverseSelectionModel(UniverseSettings universeSettings)
///
public override IEnumerable SelectCoarse(QCAlgorithm algorithm, IEnumerable coarse)
{
+ // Check if this method was overridden in Python
+ if (TryInvokePythonOverride(nameof(SelectCoarse), out IEnumerable result, algorithm, coarse))
+ {
+ return result;
+ }
+
if (algorithm.Time.Month == _lastMonth)
{
return Universe.Unchanged;
@@ -96,6 +102,12 @@ orderby x.DollarVolume descending
///
public override IEnumerable SelectFine(QCAlgorithm algorithm, IEnumerable fine)
{
+ // Check if this method was overridden in Python
+ if (TryInvokePythonOverride(nameof(SelectFine), out IEnumerable result, algorithm, fine))
+ {
+ return result;
+ }
+
var filteredFine =
(from x in fine
where x.CompanyReference.CountryId == "USA" &&
@@ -121,7 +133,7 @@ public override IEnumerable SelectFine(QCAlgorithm algorithm, IEnumerabl
// select stocks with top dollar volume in every single sector
var topFineBySector =
(from x in filteredFine
- // Group by sector
+ // Group by sector
group x by x.CompanyReference.IndustryTemplateCode into g
let y = from item in g
orderby _dollarVolumeBySymbol[item.Symbol] descending
diff --git a/Algorithm.Python/BasicTemplateOptionEquityStrategyAlgorithm.py b/Algorithm.Python/BasicTemplateOptionEquityStrategyAlgorithm.py
index 3fb20107fa2e..baf9ab4d59b0 100644
--- a/Algorithm.Python/BasicTemplateOptionEquityStrategyAlgorithm.py
+++ b/Algorithm.Python/BasicTemplateOptionEquityStrategyAlgorithm.py
@@ -33,7 +33,7 @@ def initialize(self) -> None:
self._option_symbol = option.symbol
# set our strike/expiry filter for this option chain
- option.set_filter(lambda u: (u.strikes(-2, +2)
+ option.set_filter(lambda u: (u.standards_only().strikes(-2, +2)
# Expiration method accepts TimeSpan objects or integer for days.
# The following statements yield the same filtering criteria
.expiration(0, 180)))
diff --git a/Algorithm.Python/BasicTemplateOptionStrategyAlgorithm.py b/Algorithm.Python/BasicTemplateOptionStrategyAlgorithm.py
index f4414a3f0f9e..f4fefbbb4fc9 100644
--- a/Algorithm.Python/BasicTemplateOptionStrategyAlgorithm.py
+++ b/Algorithm.Python/BasicTemplateOptionStrategyAlgorithm.py
@@ -39,8 +39,7 @@ def initialize(self):
# set our strike/expiry filter for this option chain
# SetFilter method accepts timedelta objects or integer for days.
# The following statements yield the same filtering criteria
- option.set_filter(-2, +2, 0, 180)
- # option.set_filter(-2,2, timedelta(0), timedelta(180))
+ option.set_filter(lambda u: (u.standards_only().strikes(-2, +2).expiration(0, 180)))
# use the underlying equity as the benchmark
self.set_benchmark("GOOG")
diff --git a/Algorithm.Python/BasicTemplateOptionsAlgorithm.py b/Algorithm.Python/BasicTemplateOptionsAlgorithm.py
index 3a319c65038e..93272b8f1f5c 100644
--- a/Algorithm.Python/BasicTemplateOptionsAlgorithm.py
+++ b/Algorithm.Python/BasicTemplateOptionsAlgorithm.py
@@ -34,7 +34,7 @@ def initialize(self):
self.option_symbol = option.symbol
# set our strike/expiry filter for this option chain
- option.set_filter(lambda u: (u.strikes(-2, +2)
+ option.set_filter(lambda u: (u.standards_only().strikes(-2, +2)
# Expiration method accepts TimeSpan objects or integer for days.
# The following statements yield the same filtering criteria
.expiration(0, 180)))
diff --git a/Algorithm.Python/BasicTemplateOptionsHourlyAlgorithm.py b/Algorithm.Python/BasicTemplateOptionsHourlyAlgorithm.py
index 18c9e127ac18..836838c49c69 100644
--- a/Algorithm.Python/BasicTemplateOptionsHourlyAlgorithm.py
+++ b/Algorithm.Python/BasicTemplateOptionsHourlyAlgorithm.py
@@ -34,7 +34,7 @@ def initialize(self):
self.option_symbol = option.symbol
# set our strike/expiry filter for this option chain
- option.set_filter(lambda u: (u.strikes(-2, +2)
+ option.set_filter(lambda u: (u.standards_only().strikes(-2, +2)
# Expiration method accepts TimeSpan objects or integer for days.
# The following statements yield the same filtering criteria
.expiration(0, 180)))
diff --git a/Algorithm.Python/Benchmarks/EmptySPXOptionChainBenchmark.py b/Algorithm.Python/Benchmarks/EmptySPXOptionChainBenchmark.py
new file mode 100644
index 000000000000..526c28ab24ae
--- /dev/null
+++ b/Algorithm.Python/Benchmarks/EmptySPXOptionChainBenchmark.py
@@ -0,0 +1,23 @@
+# 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.
+
+from AlgorithmImports import *
+
+class EmptySPXOptionChainBenchmark(QCAlgorithm):
+
+ def initialize(self):
+ self.set_start_date(2018, 1, 1)
+ self.set_end_date(2020, 6, 1)
+ self._index = self.add_index("SPX")
+ option = self.add_option(self._index)
+ option.set_filter(lambda u: u.include_weeklys().strikes(-30, 30).expiration(0, 7))
diff --git a/Algorithm.Python/ComboOrderTicketDemoAlgorithm.py b/Algorithm.Python/ComboOrderTicketDemoAlgorithm.py
index 41b6516bca4c..350d6d409719 100644
--- a/Algorithm.Python/ComboOrderTicketDemoAlgorithm.py
+++ b/Algorithm.Python/ComboOrderTicketDemoAlgorithm.py
@@ -28,7 +28,7 @@ def initialize(self) -> None:
option = self.add_option(equity.symbol, fill_forward=True)
self._option_symbol = option.symbol
- option.set_filter(lambda u: u.strikes(-2, +2).expiration(0, 180))
+ option.set_filter(lambda u: u.standards_only().strikes(-2, +2).expiration(0, 180))
self._open_market_orders = []
self._open_leg_limit_orders = []
diff --git a/Algorithm.Python/ConsolidateRegressionAlgorithm.py b/Algorithm.Python/ConsolidateRegressionAlgorithm.py
index 90b54060b310..bf3f9eead8a7 100644
--- a/Algorithm.Python/ConsolidateRegressionAlgorithm.py
+++ b/Algorithm.Python/ConsolidateRegressionAlgorithm.py
@@ -25,7 +25,7 @@ def initialize(self):
self.set_end_date(2020, 1, 20)
SP500 = Symbol.create(Futures.Indices.SP_500_E_MINI, SecurityType.FUTURE, Market.CME)
- symbol = list(self.futures_chain(SP500))[0]
+ symbol = list(sorted(self.futures_chain(SP500).contracts.keys(), key=lambda symbol: symbol.id.date))[0]
self._future = self.add_future_contract(symbol)
tradable_dates_count = len(list(Time.each_tradeable_day_in_time_zone(self._future.exchange.hours,
@@ -69,17 +69,12 @@ def initialize(self):
# custom data
self._custom_data_consolidator = 0
- custom_symbol = self.add_data(Bitcoin, "BTC", Resolution.DAILY).symbol
+ custom_symbol = self.add_data(Bitcoin, "BTC", Resolution.MINUTE).symbol
self.consolidate(custom_symbol, timedelta(1), lambda bar: self.increment_counter(1))
- self._custom_data_consolidator2 = 0
- self.consolidate(custom_symbol, Resolution.DAILY, lambda bar: self.increment_counter(2))
-
def increment_counter(self, id):
if id == 1:
self._custom_data_consolidator += 1
- if id == 2:
- self._custom_data_consolidator2 += 1
def update_trade_bar(self, bar, position):
self._smas[position].update(bar.end_time, bar.volume)
@@ -113,9 +108,6 @@ def on_end_of_algorithm(self):
if self._custom_data_consolidator == 0:
raise ValueError("Custom data consolidator did not consolidate any data")
- if self._custom_data_consolidator2 == 0:
- raise ValueError("Custom data consolidator 2 did not consolidate any data")
-
for i, sma in enumerate(self._smas):
if sma.samples != self._expected_consolidation_counts[i]:
raise AssertionError(f"Expected {self._expected_consolidation_counts[i]} samples in each SMA but found {sma.samples} in SMA in index {i}")
diff --git a/Algorithm.Python/CustomDataUniverseRegressionAlgorithm.py b/Algorithm.Python/CustomDataUniverseRegressionAlgorithm.py
index 871fd2b22174..c7f16e7080a9 100644
--- a/Algorithm.Python/CustomDataUniverseRegressionAlgorithm.py
+++ b/Algorithm.Python/CustomDataUniverseRegressionAlgorithm.py
@@ -67,16 +67,18 @@ def on_end_of_algorithm(self):
if len(self._selection_time) != 0:
raise ValueError(f"Unexpected selection times, missing {len(self._selection_time)}")
- def OnSecuritiesChanged(self, changes):
- for security in changes.AddedSecurities:
+ def on_securities_changed(self, changes):
+ for security in changes.added_securities:
if security.symbol.security_type == SecurityType.BASE:
continue
- self.current_underlying_symbols.add(security.Symbol)
+ self.current_underlying_symbols.add(security.symbol)
- for security in changes.RemovedSecurities:
- if security.symbol.security_type == SecurityType.BASE:
+ for security in changes.removed_securities:
+ if (security.symbol.security_type == SecurityType.BASE or
+ # This check can be removed after GH issue #9055 is resolved
+ not security.symbol in self.current_underlying_symbols):
continue
- self.current_underlying_symbols.remove(security.Symbol)
+ self.current_underlying_symbols.remove(security.symbol)
class MyPyCustomData(PythonData):
diff --git a/Algorithm.Python/ETFConstituentUniverseCompositeDelistingRegressionAlgorithm.py b/Algorithm.Python/ETFConstituentUniverseCompositeDelistingRegressionAlgorithm.py
index 43beb8cf3a61..9563b7f66d49 100644
--- a/Algorithm.Python/ETFConstituentUniverseCompositeDelistingRegressionAlgorithm.py
+++ b/Algorithm.Python/ETFConstituentUniverseCompositeDelistingRegressionAlgorithm.py
@@ -59,16 +59,16 @@ def on_securities_changed(self, changes):
raise AssertionError("New securities added after ETF constituents were delisted")
# Since we added the etf subscription it will get delisted and send us a removal event
- expected_changes_count = self.universe_symbol_count + 1
+ expected_changes_count = self.universe_symbol_count
if self.universe_selection_done:
# "_universe_symbol_count + 1" because selection is done right away,
# so AddedSecurities includes all ETF constituents (including APPL) plus GDVD
- self.universe_added = self.universe_added or len(changes.added_securities) == expected_changes_count
+ self.universe_added = self.universe_added or len(changes.added_securities) == (expected_changes_count - 1)
# TODO: shouldn't be sending AAPL as a removed security since it was added by another universe
self.universe_removed = self.universe_removed or (
- len(changes.removed_securities) == expected_changes_count and
+ len(changes.removed_securities) == (expected_changes_count + 1) and
self.utc_time.date() >= self.delisting_date and
self.utc_time.date() < self.end_date.date())
diff --git a/Algorithm.Python/ETFConstituentUniverseCompositeDelistingRegressionAlgorithmNoAddEquityETF.py b/Algorithm.Python/ETFConstituentUniverseCompositeDelistingRegressionAlgorithmNoAddEquityETF.py
index 7d43efabcc91..84eb91912beb 100644
--- a/Algorithm.Python/ETFConstituentUniverseCompositeDelistingRegressionAlgorithmNoAddEquityETF.py
+++ b/Algorithm.Python/ETFConstituentUniverseCompositeDelistingRegressionAlgorithmNoAddEquityETF.py
@@ -59,7 +59,7 @@ def on_securities_changed(self, changes):
raise AssertionError("New securities added after ETF constituents were delisted")
if self.universe_selection_done:
- self.universe_added = self.universe_added or len(changes.added_securities) == self.universe_symbol_count
+ self.universe_added = self.universe_added or len(changes.added_securities) == self.universe_symbol_count - 1
# TODO: shouldn't be sending AAPL as a removed security since it was added by another universe
self.universe_removed = self.universe_removed or (
diff --git a/Algorithm.Python/FutureOptionMultipleContractsInDifferentContractMonthsWithSameUnderlyingFutureRegressionAlgorithm.py b/Algorithm.Python/FutureOptionMultipleContractsInDifferentContractMonthsWithSameUnderlyingFutureRegressionAlgorithm.py
index 3c03d01ea882..9fef1513b7f2 100644
--- a/Algorithm.Python/FutureOptionMultipleContractsInDifferentContractMonthsWithSameUnderlyingFutureRegressionAlgorithm.py
+++ b/Algorithm.Python/FutureOptionMultipleContractsInDifferentContractMonthsWithSameUnderlyingFutureRegressionAlgorithm.py
@@ -26,7 +26,7 @@ def initialize(self):
self._create_option(datetime(2020, 2, 25), OptionRight.CALL, 1600.0): False,
self._create_option(datetime(2020, 2, 25), OptionRight.PUT, 1545.0): False
}
-
+
# Required for FOPs to use extended hours, until GH #6491 is addressed
self.universe_settings.extended_market_hours = True
@@ -34,9 +34,9 @@ def initialize(self):
self.set_end_date(2020, 1, 6)
gold_futures = self.add_future("GC", Resolution.MINUTE, Market.COMEX, extended_market_hours=True)
- gold_futures.SetFilter(0, 365)
+ gold_futures.set_filter(0, 365)
- self.add_future_option(gold_futures.Symbol)
+ self.add_future_option(gold_futures.symbol)
def on_data(self, data: Slice):
for symbol in data.quote_bars.keys():
diff --git a/Algorithm.Python/HistoryAlgorithm.py b/Algorithm.Python/HistoryAlgorithm.py
index 999341caa90a..988dc35c96ef 100644
--- a/Algorithm.Python/HistoryAlgorithm.py
+++ b/Algorithm.Python/HistoryAlgorithm.py
@@ -32,7 +32,7 @@ def initialize(self):
self.add_equity("SPY", Resolution.DAILY)
IBM = self.add_data(CustomDataEquity, "IBM", Resolution.DAILY)
# specifying the exchange will allow the history methods that accept a number of bars to return to work properly
- IBM.Exchange = EquityExchange()
+ IBM.exchange = EquityExchange()
# we can get history in initialize to set up indicators and such
self.daily_sma = SimpleMovingAverage(14)
@@ -96,7 +96,7 @@ def initialize(self):
self.assert_history_count("History(CustomDataEquity, self.securities.keys(), 14)", all_custom_data, 14 * 2)
# NOTE: Using different resolutions require that they are properly implemented in your data type. If your
- # custom data source has different resolutions, it would need to be implemented in the GetSource and
+ # custom data source has different resolutions, it would need to be implemented in the GetSource and
# Reader methods properly.
#custom_data_history = self.history(CustomDataEquity, "IBM", timedelta(7), Resolution.MINUTE)
#custom_data_history = self.history(CustomDataEquity, "IBM", 14, Resolution.MINUTE)
diff --git a/Algorithm.Python/HistoryWithCustomDataSourceRegressionAlgorithm.py b/Algorithm.Python/HistoryWithCustomDataSourceRegressionAlgorithm.py
index 7574caf39008..282b1ecf95bc 100644
--- a/Algorithm.Python/HistoryWithCustomDataSourceRegressionAlgorithm.py
+++ b/Algorithm.Python/HistoryWithCustomDataSourceRegressionAlgorithm.py
@@ -55,6 +55,7 @@ def get_source(self, config, date, is_live_mode):
def reader(self, config, line, date, is_live_mode):
trade_bar = TradeBar.parse_equity(config, line, date)
data = CustomData()
+ data.Symbol = config.symbol
data.time = trade_bar.time
data.value = trade_bar.value
data.close = trade_bar.close
diff --git a/Algorithm.Python/NullBuyingPowerOptionBullCallSpreadAlgorithm.py b/Algorithm.Python/NullBuyingPowerOptionBullCallSpreadAlgorithm.py
index f11f467b7458..65774782a1d8 100644
--- a/Algorithm.Python/NullBuyingPowerOptionBullCallSpreadAlgorithm.py
+++ b/Algorithm.Python/NullBuyingPowerOptionBullCallSpreadAlgorithm.py
@@ -33,7 +33,7 @@ def initialize(self):
option = self.add_option(equity.symbol)
self.option_symbol = option.symbol
- option.set_filter(-2, 2, 0, 180)
+ option.set_filter(lambda u: u.standards_only().strikes(-2, +2).expiration(0, 180))
def on_data(self, slice):
if self.portfolio.invested or not self.is_market_open(self.option_symbol):
diff --git a/Algorithm.Python/NullMarginMultipleOrdersRegressionAlgorithm.py b/Algorithm.Python/NullMarginMultipleOrdersRegressionAlgorithm.py
index 6a90364af53d..818b576a14d2 100644
--- a/Algorithm.Python/NullMarginMultipleOrdersRegressionAlgorithm.py
+++ b/Algorithm.Python/NullMarginMultipleOrdersRegressionAlgorithm.py
@@ -32,7 +32,7 @@ def initialize(self):
option = self.add_option(equity.symbol, fill_forward=True)
self._option_symbol = option.symbol
- option.set_filter(lambda u: u.strikes(-2, +2).expiration(0, 180))
+ option.set_filter(lambda u: u.standards_only().strikes(-2, +2).expiration(0, 180))
def on_data(self, data: Slice):
if not self.portfolio.invested:
diff --git a/Algorithm.Python/OptionChainApisConsistencyRegressionAlgorithm.py b/Algorithm.Python/OptionChainApisConsistencyRegressionAlgorithm.py
index 12d31d6919ab..702a20dd7bb6 100644
--- a/Algorithm.Python/OptionChainApisConsistencyRegressionAlgorithm.py
+++ b/Algorithm.Python/OptionChainApisConsistencyRegressionAlgorithm.py
@@ -28,10 +28,10 @@ def initialize(self) -> None:
option = self.get_option()
- option_chain_from_algorithm_api = [x.symbol for x in self.option_chain(option.symbol).contracts.values()]
+ option_chain_from_algorithm_api = self.option_chain(option.symbol).contracts.keys()
exchange_time = Extensions.convert_from_utc(self.utc_time, option.exchange.time_zone)
- option_chain_from_provider_api = list(self.option_chain_provider.get_option_contract_list(option.symbol, exchange_time))
+ option_chain_from_provider_api = list(sorted(self.option_chain_provider.get_option_contract_list(option.symbol, exchange_time)))
if len(option_chain_from_algorithm_api) == 0:
raise AssertionError("No options in chain from algorithm API")
diff --git a/Algorithm.Python/OptionChainIncludeWeeklysByDefaultRegressionAlgorithm.py b/Algorithm.Python/OptionChainIncludeWeeklysByDefaultRegressionAlgorithm.py
new file mode 100644
index 000000000000..c914d2d62dca
--- /dev/null
+++ b/Algorithm.Python/OptionChainIncludeWeeklysByDefaultRegressionAlgorithm.py
@@ -0,0 +1,46 @@
+# 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.
+
+from AlgorithmImports import *
+
+###
+### Verifies that weekly option contracts are included when no standard contracts are available.
+###
+class OptionChainIncludeWeeklysByDefaultRegressionAlgorithm(QCAlgorithm):
+
+ def initialize(self):
+ self.set_start_date(2015, 12, 24)
+ self.set_end_date(2015, 12, 24)
+
+ self.option = self.add_option("GOOG")
+ self.option_symbol = self.option.Symbol
+
+ self.option.set_filter(lambda u: u.strikes(-8, 8).expiration(0, 0))
+
+ self.weekly_count = 0
+ self.total_count = 0
+
+ def on_data(self, data):
+ chain = data.option_chains.get(self.option_symbol)
+ if chain:
+ self.total_count += len(chain.contracts)
+ for contract in chain.contracts.values():
+ if not OptionSymbol.is_standard(contract.symbol):
+ self.weekly_count += 1
+
+ def on_end_of_algorithm(self):
+ if self.weekly_count == 0:
+ raise RegressionTestException("No weekly contracts found")
+
+ if self.total_count != self.weekly_count:
+ raise RegressionTestException("When no standard option expirations are available, the option chain must fall back to weekly contracts only")
\ No newline at end of file
diff --git a/Algorithm.Python/OptionChainedUniverseSelectionModelRegressionAlgorithm.py b/Algorithm.Python/OptionChainedUniverseSelectionModelRegressionAlgorithm.py
index e800f1fa47e6..d42a5a0d7948 100644
--- a/Algorithm.Python/OptionChainedUniverseSelectionModelRegressionAlgorithm.py
+++ b/Algorithm.Python/OptionChainedUniverseSelectionModelRegressionAlgorithm.py
@@ -28,7 +28,7 @@ def initialize(self):
self.add_universe_selection(
OptionChainedUniverseSelectionModel(
universe,
- lambda u: (u.strikes(-2, +2)
+ lambda u: (u.standards_only().strikes(-2, +2)
# Expiration method accepts TimeSpan objects or integer for days.
# The following statements yield the same filtering criteria
.expiration(0, 180))
diff --git a/Algorithm.Python/OptionPriceModelForSupportedAmericanOptionRegressionAlgorithm.py b/Algorithm.Python/OptionPriceModelForSupportedAmericanOptionRegressionAlgorithm.py
index a9b495c4bbaa..a87ff4cbe450 100644
--- a/Algorithm.Python/OptionPriceModelForSupportedAmericanOptionRegressionAlgorithm.py
+++ b/Algorithm.Python/OptionPriceModelForSupportedAmericanOptionRegressionAlgorithm.py
@@ -24,6 +24,8 @@ def initialize(self):
self.set_end_date(2014, 6, 9)
option = self.add_option("AAPL", Resolution.MINUTE)
+ option.set_filter(lambda u: u.standards_only().strikes(-1, 1).expiration(0, 35))
+
# BaroneAdesiWhaley model supports American style options
option.price_model = OptionPriceModels.barone_adesi_whaley()
diff --git a/Algorithm.Python/OptionPriceModelForUnsupportedAmericanOptionRegressionAlgorithm.py b/Algorithm.Python/OptionPriceModelForUnsupportedAmericanOptionRegressionAlgorithm.py
index ce78c8e0adb6..072af5b2496b 100644
--- a/Algorithm.Python/OptionPriceModelForUnsupportedAmericanOptionRegressionAlgorithm.py
+++ b/Algorithm.Python/OptionPriceModelForUnsupportedAmericanOptionRegressionAlgorithm.py
@@ -24,6 +24,8 @@ def initialize(self):
self.set_end_date(2014, 6, 9)
option = self.add_option("AAPL", Resolution.MINUTE)
+ option.set_filter(lambda u: u.standards_only().strikes(-1, 1).expiration(0, 35))
+
# BlackSholes model does not support American style options
option.price_model = OptionPriceModels.black_scholes()
diff --git a/Algorithm.Python/OptionStrategyFactoryMethodsBaseAlgorithm.py b/Algorithm.Python/OptionStrategyFactoryMethodsBaseAlgorithm.py
index 08bc1ba27175..a2fb5fe8f16f 100644
--- a/Algorithm.Python/OptionStrategyFactoryMethodsBaseAlgorithm.py
+++ b/Algorithm.Python/OptionStrategyFactoryMethodsBaseAlgorithm.py
@@ -27,7 +27,7 @@ def initialize(self):
option = self.add_option("GOOG")
self._option_symbol = option.symbol
- option.set_filter(-2, +2, 0, 180)
+ option.set_filter(lambda u: u.standards_only().strikes(-2, +2).expiration(0, 180))
self.set_benchmark("GOOG")
diff --git a/Algorithm.Python/QuantConnect.Algorithm.Python.csproj b/Algorithm.Python/QuantConnect.Algorithm.Python.csproj
index 27d959076f69..28a7eb1304fc 100644
--- a/Algorithm.Python/QuantConnect.Algorithm.Python.csproj
+++ b/Algorithm.Python/QuantConnect.Algorithm.Python.csproj
@@ -4,7 +4,7 @@
AnyCPU
QuantConnect.Algorithm.Python
QuantConnect.Algorithm.Python
- net9.0
+ net10.0
AllEnabledByDefault
bin\$(Configuration)\
false
@@ -37,7 +37,7 @@
-
+
diff --git a/Algorithm.Python/ScheduledQueuingAlgorithm.py b/Algorithm.Python/ScheduledQueuingAlgorithm.py
index fc826a7dfe98..dc1866d847ab 100644
--- a/Algorithm.Python/ScheduledQueuingAlgorithm.py
+++ b/Algorithm.Python/ScheduledQueuingAlgorithm.py
@@ -20,18 +20,18 @@ def initialize(self) -> None:
self.set_start_date(2020, 9, 1)
self.set_end_date(2020, 9, 2)
self.set_cash(100000)
-
+
self.__number_of_symbols = 2000
self.__number_of_symbols_fine = 1000
self.set_universe_selection(FineFundamentalUniverseSelectionModel(self.coarse_selection_function, self.fine_selection_function, None))
-
+
self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
-
+
self.set_execution(ImmediateExecutionModel())
-
+
self._queue = Queue()
self._dequeue_size = 100
-
+
self.add_equity("SPY", Resolution.MINUTE)
self.schedule.on(self.date_rules.every_day("SPY"), self.time_rules.at(0, 0), self.fill_queue)
self.schedule.on(self.date_rules.every_day("SPY"), self.time_rules.every(timedelta(minutes=60)), self.take_from_queue)
@@ -40,22 +40,22 @@ def coarse_selection_function(self, coarse: list[CoarseFundamental]) -> list[Sym
has_fundamentals = [security for security in coarse if security.has_fundamental_data]
sorted_by_dollar_volume = sorted(has_fundamentals, key=lambda x: x.dollar_volume, reverse=True)
return [ x.symbol for x in sorted_by_dollar_volume[:self.__number_of_symbols] ]
-
+
def fine_selection_function(self, fine: list[FineFundamental]) -> list[Symbol]:
sorted_by_pe_ratio = sorted(fine, key=lambda x: x.valuation_ratios.pe_ratio, reverse=True)
return [ x.symbol for x in sorted_by_pe_ratio[:self.__number_of_symbols_fine] ]
-
+
def fill_queue(self) -> None:
- securities = [security for security in self.active_securities.values if security.fundamentals]
-
+ securities = [security for security in self.active_securities.values() if security.fundamentals]
+
# Fill queue with symbols sorted by PE ratio (decreasing order)
self._queue.queue.clear()
sorted_by_pe_ratio = sorted(securities, key=lambda x: x.fundamentals.valuation_ratios.pe_ratio, reverse=True)
for security in sorted_by_pe_ratio:
self._queue.put(security.symbol)
-
+
def take_from_queue(self) -> None:
symbols = [self._queue.get() for _ in range(min(self._dequeue_size, self._queue.qsize()))]
self.history(symbols, 10, Resolution.DAILY)
-
+
self.log(f"Symbols at {self.time}: {[str(symbol) for symbol in symbols]}")
diff --git a/Algorithm/Alphas/AlphaModel.cs b/Algorithm/Alphas/AlphaModel.cs
index 578b48ac8d20..1d284ddb3531 100644
--- a/Algorithm/Alphas/AlphaModel.cs
+++ b/Algorithm/Alphas/AlphaModel.cs
@@ -17,13 +17,14 @@
using System.Collections.Generic;
using QuantConnect.Data;
using QuantConnect.Data.UniverseSelection;
+using QuantConnect.Python;
namespace QuantConnect.Algorithm.Framework.Alphas
{
///
/// Provides a base class for alpha models.
///
- public class AlphaModel : IAlphaModel, INamedModel
+ public class AlphaModel : BasePythonWrapper, IAlphaModel, INamedModel
{
///
/// Defines a name for a framework model
@@ -47,7 +48,7 @@ public AlphaModel()
/// The new insights generated
public virtual IEnumerable Update(QCAlgorithm algorithm, Slice data)
{
- throw new System.NotImplementedException("Types deriving from 'AlphaModel' must implement the 'IEnumerable Update(QCAlgorithm, Slice) method.");
+ throw new NotImplementedException("Types deriving from 'AlphaModel' must implement the 'IEnumerable Update(QCAlgorithm, Slice) method.");
}
///
diff --git a/Algorithm/Alphas/AlphaModelPythonWrapper.cs b/Algorithm/Alphas/AlphaModelPythonWrapper.cs
index a12410f8cad9..32fb50c69397 100644
--- a/Algorithm/Alphas/AlphaModelPythonWrapper.cs
+++ b/Algorithm/Alphas/AlphaModelPythonWrapper.cs
@@ -27,8 +27,6 @@ namespace QuantConnect.Algorithm.Framework.Alphas
///
public class AlphaModelPythonWrapper : AlphaModel
{
- private readonly BasePythonWrapper _model;
-
///
/// Defines a name for a framework model
///
@@ -39,13 +37,13 @@ public override string Name
using (Py.GIL())
{
// if the model defines a Name property then use that
- if (_model.HasAttr(nameof(Name)))
+ if (HasAttr(nameof(Name)))
{
- return _model.GetProperty(nameof(Name));
+ return GetProperty(nameof(Name));
}
// if the model does not define a name property, use the python type name
- return _model.GetProperty(" __class__" ).GetAttr("__name__").GetAndDispose();
+ return GetProperty(" __class__").GetAttr("__name__").GetAndDispose();
}
}
}
@@ -56,14 +54,20 @@ public override string Name
/// >Model that generates alpha
public AlphaModelPythonWrapper(PyObject model)
{
- _model = new BasePythonWrapper(model, false);
+ SetPythonInstance(model, false);
foreach (var attributeName in new[] { "Update", "OnSecuritiesChanged" })
{
- if (!_model.HasAttr(attributeName))
+ if (!HasAttr(attributeName))
{
throw new NotImplementedException($"IAlphaModel.{attributeName} must be implemented. Please implement this missing method on {model.GetPythonType()}");
}
}
+
+ var methodName = nameof(SetPythonInstance);
+ if (HasAttr(methodName))
+ {
+ InvokeMethod(methodName, model);
+ }
}
///
@@ -75,7 +79,7 @@ public AlphaModelPythonWrapper(PyObject model)
/// The new insights generated
public override IEnumerable Update(QCAlgorithm algorithm, Slice data)
{
- return _model.InvokeMethodAndEnumerate(nameof(Update), algorithm, data);
+ return InvokeMethodAndEnumerate(nameof(Update), algorithm, data);
}
///
@@ -85,7 +89,7 @@ public override IEnumerable Update(QCAlgorithm algorithm, Slice data)
/// The security additions and removals from the algorithm
public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
{
- _model.InvokeVoidMethod(nameof(OnSecuritiesChanged), algorithm, changes);
+ InvokeVoidMethod(nameof(OnSecuritiesChanged), algorithm, changes);
}
}
}
diff --git a/Algorithm/Alphas/CompositeAlphaModel.cs b/Algorithm/Alphas/CompositeAlphaModel.cs
index b203805307b0..068b6d2b5503 100644
--- a/Algorithm/Alphas/CompositeAlphaModel.cs
+++ b/Algorithm/Alphas/CompositeAlphaModel.cs
@@ -116,11 +116,10 @@ public void AddAlpha(IAlphaModel alphaModel)
/// The alpha model to add
public void AddAlpha(PyObject pyAlphaModel)
{
- IAlphaModel alphaModel;
- if (!pyAlphaModel.TryConvert(out alphaModel))
- {
- alphaModel = new AlphaModelPythonWrapper(pyAlphaModel);
- }
+ var alphaModel = PythonUtil.CreateInstanceOrWrapper(
+ pyAlphaModel,
+ py => new AlphaModelPythonWrapper(py)
+ );
_alphaModels.Add(alphaModel);
}
}
diff --git a/Algorithm/ConstituentUniverseDefinitions.cs b/Algorithm/ConstituentUniverseDefinitions.cs
index e83ffebc92a7..54b1e63c62eb 100644
--- a/Algorithm/ConstituentUniverseDefinitions.cs
+++ b/Algorithm/ConstituentUniverseDefinitions.cs
@@ -29,7 +29,7 @@ public class ConstituentUniverseDefinitions
private readonly IAlgorithm _algorithm;
///
- /// Universe which selects companies whose revenues and earnings have both been growing significantly faster than
+ /// which selects companies whose revenues and earnings have both been growing significantly faster than
/// the general economy.
///
public Universe AggressiveGrowth(UniverseSettings universeSettings = null)
@@ -40,7 +40,7 @@ public Universe AggressiveGrowth(UniverseSettings universeSettings = null)
}
///
- /// Universe which selects companies that are growing respectably faster than the general economy, and often pay a
+ /// which selects companies that are growing respectably faster than the general economy, and often pay a
/// steady dividend. They tend to be mature and solidly profitable businesses.
///
public Universe ClassicGrowth(UniverseSettings universeSettings = null)
@@ -51,7 +51,7 @@ public Universe ClassicGrowth(UniverseSettings universeSettings = null)
}
///
- /// Universe which selects companies in the cyclicals and durables sectors, except those in the three types below.
+ /// which selects companies in the cyclicals and durables sectors, except those in the three types below.
/// The profits of cyclicals tend to rise and fall with the general economy.
///
public Universe Cyclicals(UniverseSettings universeSettings = null)
@@ -62,7 +62,7 @@ public Universe Cyclicals(UniverseSettings universeSettings = null)
}
///
- /// Universe which selects companies that have had consistently declining cash flows and earnings over the past
+ /// which selects companies that have had consistently declining cash flows and earnings over the past
/// three years, and/or very high debt.
///
public Universe Distressed(UniverseSettings universeSettings = null)
@@ -73,7 +73,7 @@ public Universe Distressed(UniverseSettings universeSettings = null)
}
///
- /// Universe which selects companies that deal in assets such as oil, metals, and real estate, which tend to do
+ /// which selects companies that deal in assets such as oil, metals, and real estate, which tend to do
/// well in inflationary environments.
///
public Universe HardAsset(UniverseSettings universeSettings = null)
@@ -84,7 +84,7 @@ public Universe HardAsset(UniverseSettings universeSettings = null)
}
///
- /// Universe which selects companies that have dividend yields at least twice the average for large-cap stocks.
+ /// which selects companies that have dividend yields at least twice the average for large-cap stocks.
/// They tend to be mature, slow-growing companies.
///
public Universe HighYield(UniverseSettings universeSettings = null)
@@ -95,7 +95,7 @@ public Universe HighYield(UniverseSettings universeSettings = null)
}
///
- /// Universe which selects companies that have shown slow revenue and earnings growth (typically less than the rate
+ /// which selects companies that have shown slow revenue and earnings growth (typically less than the rate
/// of GDP growth) over at least three years.
///
public Universe SlowGrowth(UniverseSettings universeSettings = null)
@@ -106,7 +106,7 @@ public Universe SlowGrowth(UniverseSettings universeSettings = null)
}
///
- /// Universe which selects companies that have shown strong revenue growth but slower or spotty earnings growth.
+ /// which selects companies that have shown strong revenue growth but slower or spotty earnings growth.
/// Very small or young companies also tend to fall into this class.
///
public Universe SpeculativeGrowth(UniverseSettings universeSettings = null)
diff --git a/Algorithm/DollarVolumeUniverseDefinitions.cs b/Algorithm/DollarVolumeUniverseDefinitions.cs
index 191f911a2101..bee8d69de266 100644
--- a/Algorithm/DollarVolumeUniverseDefinitions.cs
+++ b/Algorithm/DollarVolumeUniverseDefinitions.cs
@@ -40,14 +40,14 @@ public DollarVolumeUniverseDefinitions(QCAlgorithm algorithm)
}
///
- /// Creates a new coarse universe that contains the top count of stocks
+ /// Creates a new coarse that contains the top count of stocks
/// by daily dollar volume
///
/// The number of stock to select
/// The settings for stocks added by this universe.
/// Defaults to
/// A new coarse universe for the top count of stocks by dollar volume
- [Obsolete("This method is deprecated. Use method `Universe.DollarVolume.Top(...)` instead")]
+ [Obsolete("This method is deprecated. Use method `Universe.Top(...)` instead")]
public Universe Top(int count, UniverseSettings universeSettings = null)
{
return _algorithm.Universe.Top(count, universeSettings);
diff --git a/Algorithm/Execution/ExecutionModel.cs b/Algorithm/Execution/ExecutionModel.cs
index b1498fae6033..5407cd10876d 100644
--- a/Algorithm/Execution/ExecutionModel.cs
+++ b/Algorithm/Execution/ExecutionModel.cs
@@ -16,13 +16,14 @@
using QuantConnect.Algorithm.Framework.Portfolio;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Orders;
+using QuantConnect.Python;
namespace QuantConnect.Algorithm.Framework.Execution
{
///
/// Provides a base class for execution models
///
- public class ExecutionModel : IExecutionModel
+ public class ExecutionModel : BasePythonWrapper, IExecutionModel
{
///
/// If true, orders should be submitted asynchronously.
diff --git a/Algorithm/Execution/ExecutionModelPythonWrapper.cs b/Algorithm/Execution/ExecutionModelPythonWrapper.cs
index 3b1520d02980..bfc7848ab390 100644
--- a/Algorithm/Execution/ExecutionModelPythonWrapper.cs
+++ b/Algorithm/Execution/ExecutionModelPythonWrapper.cs
@@ -27,8 +27,6 @@ namespace QuantConnect.Algorithm.Framework.Execution
///
public class ExecutionModelPythonWrapper : ExecutionModel
{
- private readonly BasePythonWrapper _model;
-
private readonly bool _onOrderEventsDefined;
///
@@ -37,16 +35,22 @@ public class ExecutionModelPythonWrapper : ExecutionModel
/// Model defining how to execute trades to reach a portfolio target
public ExecutionModelPythonWrapper(PyObject model)
{
- _model = new BasePythonWrapper(model, false);
+ SetPythonInstance(model, false);
foreach (var attributeName in new[] { "Execute", "OnSecuritiesChanged" })
{
- if (!_model.HasAttr(attributeName))
+ if (!HasAttr(attributeName))
{
throw new NotImplementedException($"IExecutionModel.{attributeName} must be implemented. Please implement this missing method on {model.GetPythonType()}");
}
}
- _onOrderEventsDefined = _model.HasAttr("OnOrderEvent");
+ _onOrderEventsDefined = HasAttr("OnOrderEvent");
+
+ var methodName = nameof(SetPythonInstance);
+ if (HasAttr(methodName))
+ {
+ InvokeMethod(methodName, model);
+ }
}
///
@@ -57,7 +61,7 @@ public ExecutionModelPythonWrapper(PyObject model)
/// The portfolio targets to be ordered
public override void Execute(QCAlgorithm algorithm, IPortfolioTarget[] targets)
{
- _model.InvokeMethod(nameof(Execute), algorithm, targets).Dispose();
+ InvokeMethod(nameof(Execute), algorithm, targets).Dispose();
}
///
@@ -67,7 +71,7 @@ public override void Execute(QCAlgorithm algorithm, IPortfolioTarget[] targets)
/// The security additions and removals from the algorithm
public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
{
- _model.InvokeMethod(nameof(OnSecuritiesChanged), algorithm, changes).Dispose();
+ InvokeMethod(nameof(OnSecuritiesChanged), algorithm, changes).Dispose();
}
///
@@ -79,7 +83,7 @@ public override void OnOrderEvent(QCAlgorithm algorithm, OrderEvent orderEvent)
{
if (_onOrderEventsDefined)
{
- _model.InvokeMethod(nameof(OnOrderEvent), algorithm, orderEvent).Dispose();
+ InvokeMethod(nameof(OnOrderEvent), algorithm, orderEvent).Dispose();
}
}
}
diff --git a/Algorithm/QCAlgorithm.Framework.Python.cs b/Algorithm/QCAlgorithm.Framework.Python.cs
index bb21eaccf23f..2848b5ce32dc 100644
--- a/Algorithm/QCAlgorithm.Framework.Python.cs
+++ b/Algorithm/QCAlgorithm.Framework.Python.cs
@@ -19,6 +19,7 @@
using QuantConnect.Algorithm.Framework.Portfolio;
using QuantConnect.Algorithm.Framework.Risk;
using QuantConnect.Algorithm.Framework.Selection;
+using QuantConnect.Util;
namespace QuantConnect.Algorithm
{
@@ -31,15 +32,10 @@ public partial class QCAlgorithm
[DocumentationAttribute(AlgorithmFramework)]
public void SetAlpha(PyObject alpha)
{
- IAlphaModel model;
- if (alpha.TryConvert(out model))
- {
- SetAlpha(model);
- }
- else
- {
- Alpha = new AlphaModelPythonWrapper(alpha);
- }
+ Alpha = PythonUtil.CreateInstanceOrWrapper(
+ alpha,
+ py => new AlphaModelPythonWrapper(py)
+ );
}
///
@@ -49,15 +45,11 @@ public void SetAlpha(PyObject alpha)
[DocumentationAttribute(AlgorithmFramework)]
public void AddAlpha(PyObject alpha)
{
- IAlphaModel model;
- if (alpha.TryConvert(out model))
- {
- AddAlpha(model);
- }
- else
- {
- AddAlpha(new AlphaModelPythonWrapper(alpha));
- }
+ var model = PythonUtil.CreateInstanceOrWrapper(
+ alpha,
+ py => new AlphaModelPythonWrapper(py)
+ );
+ AddAlpha(model);
}
///
@@ -68,15 +60,10 @@ public void AddAlpha(PyObject alpha)
[DocumentationAttribute(TradingAndOrders)]
public void SetExecution(PyObject execution)
{
- IExecutionModel model;
- if (execution.TryConvert(out model))
- {
- SetExecution(model);
- }
- else
- {
- Execution = new ExecutionModelPythonWrapper(execution);
- }
+ Execution = PythonUtil.CreateInstanceOrWrapper(
+ execution,
+ py => new ExecutionModelPythonWrapper(py)
+ );
}
///
@@ -87,15 +74,10 @@ public void SetExecution(PyObject execution)
[DocumentationAttribute(TradingAndOrders)]
public void SetPortfolioConstruction(PyObject portfolioConstruction)
{
- IPortfolioConstructionModel model;
- if (portfolioConstruction.TryConvert(out model))
- {
- SetPortfolioConstruction(model);
- }
- else
- {
- PortfolioConstruction = new PortfolioConstructionModelPythonWrapper(portfolioConstruction);
- }
+ PortfolioConstruction = PythonUtil.CreateInstanceOrWrapper(
+ portfolioConstruction,
+ py => new PortfolioConstructionModelPythonWrapper(py)
+ );
}
///
@@ -106,12 +88,10 @@ public void SetPortfolioConstruction(PyObject portfolioConstruction)
[DocumentationAttribute(Universes)]
public void SetUniverseSelection(PyObject universeSelection)
{
- IUniverseSelectionModel model;
- if (!universeSelection.TryConvert(out model))
- {
- model = new UniverseSelectionModelPythonWrapper(universeSelection);
- }
- SetUniverseSelection(model);
+ UniverseSelection = PythonUtil.CreateInstanceOrWrapper(
+ universeSelection,
+ py => new UniverseSelectionModelPythonWrapper(py)
+ );
}
///
@@ -122,11 +102,10 @@ public void SetUniverseSelection(PyObject universeSelection)
[DocumentationAttribute(Universes)]
public void AddUniverseSelection(PyObject universeSelection)
{
- IUniverseSelectionModel model;
- if (!universeSelection.TryConvert(out model))
- {
- model = new UniverseSelectionModelPythonWrapper(universeSelection);
- }
+ var model = PythonUtil.CreateInstanceOrWrapper(
+ universeSelection,
+ py => new UniverseSelectionModelPythonWrapper(py)
+ );
AddUniverseSelection(model);
}
@@ -138,15 +117,10 @@ public void AddUniverseSelection(PyObject universeSelection)
[DocumentationAttribute(TradingAndOrders)]
public void SetRiskManagement(PyObject riskManagement)
{
- IRiskManagementModel model;
- if (riskManagement.TryConvert(out model))
- {
- SetRiskManagement(model);
- }
- else
- {
- RiskManagement = new RiskManagementModelPythonWrapper(riskManagement);
- }
+ RiskManagement = PythonUtil.CreateInstanceOrWrapper(
+ riskManagement,
+ py => new RiskManagementModelPythonWrapper(py)
+ );
}
///
@@ -157,11 +131,10 @@ public void SetRiskManagement(PyObject riskManagement)
[DocumentationAttribute(TradingAndOrders)]
public void AddRiskManagement(PyObject riskManagement)
{
- IRiskManagementModel model;
- if (!riskManagement.TryConvert(out model))
- {
- model = new RiskManagementModelPythonWrapper(riskManagement);
- }
+ var model = PythonUtil.CreateInstanceOrWrapper(
+ riskManagement,
+ py => new RiskManagementModelPythonWrapper(py)
+ );
AddRiskManagement(model);
}
}
diff --git a/Algorithm/QCAlgorithm.Framework.cs b/Algorithm/QCAlgorithm.Framework.cs
index ab7bf74bd673..ef46f760f651 100644
--- a/Algorithm/QCAlgorithm.Framework.cs
+++ b/Algorithm/QCAlgorithm.Framework.cs
@@ -79,8 +79,8 @@ public partial class QCAlgorithm
public IRiskManagementModel RiskManagement { get; set; }
///
- /// Called by setup handlers after Initialize and allows the algorithm a chance to organize
- /// the data gather in the Initialize method
+ /// Called by setup handlers after and allows the algorithm a chance to organize
+ /// the data gather in the method
///
[DocumentationAttribute(AlgorithmFramework)]
public void FrameworkPostInitialize()
@@ -100,7 +100,7 @@ public void FrameworkPostInitialize()
///
/// Used to send data updates to algorithm framework models
///
- /// The current data slice
+ /// The current data
[DocumentationAttribute(AlgorithmFramework)]
[DocumentationAttribute(HandlingData)]
public void OnFrameworkData(Slice slice)
@@ -166,12 +166,12 @@ public void OnFrameworkData(Slice slice)
}
///
- /// They different framework models will process the new provided insight.
+ /// They different framework models will process the new provided .
/// The will create targets,
/// the will adjust the targets
/// and the will execute the
///
- /// The insight to process
+ /// The to process
[DocumentationAttribute(AlgorithmFramework)]
private void ProcessInsights(Insight[] insights)
{
@@ -179,7 +179,7 @@ private void ProcessInsights(Insight[] insights)
var targetsEnumerable = PortfolioConstruction.CreateTargets(this, insights);
// for performance only call 'ToArray' if not empty enumerable (which is static)
var targets = targetsEnumerable == Enumerable.Empty()
- ? new IPortfolioTarget[] {} : targetsEnumerable.ToArray();
+ ? new IPortfolioTarget[] { } : targetsEnumerable.ToArray();
// set security targets w/ those generated via portfolio construction module
foreach (var target in targets)
diff --git a/Algorithm/QCAlgorithm.History.cs b/Algorithm/QCAlgorithm.History.cs
index 75d178995e62..41caa59528cc 100644
--- a/Algorithm/QCAlgorithm.History.cs
+++ b/Algorithm/QCAlgorithm.History.cs
@@ -25,12 +25,17 @@
using QuantConnect.Python;
using Python.Runtime;
using QuantConnect.Data.UniverseSelection;
-using QuantConnect.Data.Auxiliary;
+using QuantConnect.Configuration;
namespace QuantConnect.Algorithm
{
public partial class QCAlgorithm
{
+ private static readonly int SeedLookbackPeriod = Config.GetInt("seed-lookback-period", 5);
+ private static readonly int SeedRetryMinuteLookbackPeriod = Config.GetInt("seed-retry-minute-lookback-period", 24 * 60);
+ private static readonly int SeedRetryHourLookbackPeriod = Config.GetInt("seed-retry-hour-lookback-period", 24);
+ private static readonly int SeedRetryDailyLookbackPeriod = Config.GetInt("seed-retry-daily-lookback-period", 10);
+
private bool _dataDictionaryTickWarningSent;
///
@@ -713,7 +718,7 @@ public IEnumerable GetLastKnownPrices(Security security)
}
///
- /// Yields data to warmup a security for all it's subscribed data types
+ /// Yields data to warm up a security for all its subscribed data types
///
/// The symbol we want to get seed data for
/// Securities historical data
@@ -726,61 +731,47 @@ public IEnumerable GetLastKnownPrices(Symbol symbol)
return Enumerable.Empty();
}
- var result = new Dictionary();
- Resolution? resolution = null;
- Func requestData = period =>
- {
- var historyRequests = CreateBarCountHistoryRequests(new[] { symbol }, period)
- .Select(request =>
- {
- // For speed and memory usage, use Resolution.Minute as the minimum resolution
- request.Resolution = (Resolution)Math.Max((int)Resolution.Minute, (int)request.Resolution);
- // force no fill forward behavior
- request.FillForwardResolution = null;
+ var data = GetLastKnownPrices([symbol]);
+ return data.Values.FirstOrDefault() ?? Enumerable.Empty();
+ }
- resolution = request.Resolution;
- return request;
- })
- // request only those tick types we didn't get the data we wanted
- .Where(request => !result.ContainsKey(request.TickType))
- .ToList();
- foreach (var slice in History(historyRequests))
- {
- for (var i = 0; i < historyRequests.Count; i++)
- {
- var historyRequest = historyRequests[i];
- var data = slice.Get(historyRequest.DataType);
- if (data.ContainsKey(symbol))
- {
- // keep the last data point per tick type
- result[historyRequest.TickType] = (BaseData)data[symbol];
- }
- }
- }
- // true when all history requests tick types have a data point
- return historyRequests.All(request => result.ContainsKey(request.TickType));
- };
+ ///
+ /// Yields data to warm up multiple securities for all their subscribed data types
+ ///
+ /// The securities we want to get seed data for
+ /// Securities historical data
+ [DocumentationAttribute(AddingData)]
+ [DocumentationAttribute(HistoricalData)]
+ public DataDictionary> GetLastKnownPrices(IEnumerable securities)
+ {
+ return GetLastKnownPrices(securities.Select(s => s.Symbol));
+ }
- if (!requestData(5))
+ ///
+ /// Yields data to warm up multiple securities for all their subscribed data types
+ ///
+ /// The symbols we want to get seed data for
+ /// Securities historical data
+ [DocumentationAttribute(AddingData)]
+ [DocumentationAttribute(HistoricalData)]
+ public DataDictionary> GetLastKnownPrices(IEnumerable symbols)
+ {
+ if (HistoryProvider == null)
{
- if (resolution.HasValue)
- {
- // If the first attempt to get the last know price returns null, it maybe the case of an illiquid security.
- // We increase the look-back period for this case accordingly to the resolution to cover 3 trading days
- var periods =
- resolution.Value == Resolution.Daily ? 3 :
- resolution.Value == Resolution.Hour ? 24 : 1440;
- requestData(periods);
- }
- else
- {
- // this shouldn't happen but just in case
- QuantConnect.Logging.Log.Error(
- $"QCAlgorithm.GetLastKnownPrices(): no history request was created for symbol {symbol} at {Time}");
- }
+ return new DataDictionary>();
}
- // return the data ordered by time ascending
- return result.Values.OrderBy(data => data.Time);
+
+ var data = new Dictionary<(Symbol, Type, TickType), BaseData>();
+ GetLastKnownPricesImpl(symbols, data);
+
+ return data
+ .GroupBy(kvp => kvp.Key.Item1)
+ .ToDataDictionary(
+ g => g.Key,
+ g => g.OrderBy(kvp => kvp.Value.Time)
+ .ThenBy(kvp => GetTickTypeOrder(kvp.Key.Item1.SecurityType, kvp.Key.Item3))
+ .Select(kvp => kvp.Value)
+ );
}
///
@@ -795,12 +786,149 @@ public IEnumerable GetLastKnownPrices(Symbol symbol)
[DocumentationAttribute(HistoricalData)]
public BaseData GetLastKnownPrice(Security security)
{
- return GetLastKnownPrices(security.Symbol)
+ return GetLastKnownPrice(security.Symbol);
+ }
+
+ ///
+ /// Get the last known price using the history provider.
+ /// Useful for seeding securities with the correct price
+ ///
+ /// Symbol for which to retrieve historical data
+ /// A single object with the last known price
+ [Obsolete("This method is obsolete please use 'GetLastKnownPrices' which will return the last data point" +
+ " for each type associated with the requested security")]
+ [DocumentationAttribute(AddingData)]
+ [DocumentationAttribute(HistoricalData)]
+ public BaseData GetLastKnownPrice(Symbol symbol)
+ {
+ return GetLastKnownPrices(symbol)
// since we are returning a single data point let's respect order
.OrderByDescending(data => GetTickTypeOrder(data.Symbol.SecurityType, LeanData.GetCommonTickTypeForCommonDataTypes(data.GetType(), data.Symbol.SecurityType)))
.LastOrDefault();
}
+ private void GetLastKnownPricesImpl(IEnumerable symbols, Dictionary<(Symbol, Type, TickType), BaseData> result,
+ int attempts = 0, IEnumerable failedRequests = null)
+ {
+ IEnumerable historyRequests;
+ var isRetry = failedRequests != null;
+
+ symbols = symbols?.Where(x => !x.IsCanonical() || x.SecurityType == SecurityType.Future);
+
+ if (attempts == 0)
+ {
+ historyRequests = CreateBarCountHistoryRequests(symbols, SeedLookbackPeriod,
+ fillForward: false, useAllSubscriptions: true)
+ .SelectMany(request =>
+ {
+ // Make open interest request daily, higher resolutions will need greater periods to return data
+ if (request.DataType == typeof(OpenInterest) && request.Resolution < Resolution.Daily)
+ {
+ return CreateBarCountHistoryRequests([request.Symbol], typeof(OpenInterest), SeedLookbackPeriod,
+ Resolution.Daily, fillForward: false, useAllSubscriptions: true);
+ }
+
+ if (request.Resolution < Resolution.Minute)
+ {
+ var dataType = request.DataType;
+ if (dataType == typeof(Tick))
+ {
+ dataType = request.TickType == TickType.Trade ? typeof(TradeBar) : typeof(QuoteBar);
+ }
+
+ return CreateBarCountHistoryRequests([request.Symbol], dataType, SeedLookbackPeriod,
+ Resolution.Minute, fillForward: false, useAllSubscriptions: true);
+ }
+
+ return [request];
+ });
+ }
+ else if (attempts == 1)
+ {
+ // If the first attempt to get the last know price returns no data, it maybe the case of an illiquid security.
+ // We increase the look-back period for this case accordingly to the resolution to cover a longer period
+ historyRequests = failedRequests
+ .GroupBy(request => request.Symbol)
+ .Select(group =>
+ {
+ var symbolRequests = group.ToArray();
+ var resolution = symbolRequests[0].Resolution;
+ var periods = resolution == Resolution.Daily
+ ? SeedRetryDailyLookbackPeriod
+ : resolution == Resolution.Hour ? SeedRetryHourLookbackPeriod : SeedRetryMinuteLookbackPeriod;
+ return CreateBarCountHistoryRequests([group.Key], periods, resolution, fillForward: false, useAllSubscriptions: true)
+ .Where(request => symbolRequests.Any(x => x.DataType == request.DataType));
+ })
+ .SelectMany(x => x);
+ }
+ else
+ {
+ // Fall back to bigger daily requests as a last resort
+ historyRequests = CreateBarCountHistoryRequests(failedRequests.Select(x => x.Symbol).Distinct(),
+ Math.Min(60, 5 * SeedRetryDailyLookbackPeriod), Resolution.Daily, fillForward: false, useAllSubscriptions: true);
+ }
+
+ var requests = historyRequests.ToArray();
+ if (requests.Length == 0)
+ {
+ return;
+ }
+
+ foreach (var slice in History(requests))
+ {
+ for (var i = 0; i < requests.Length; i++)
+ {
+ var historyRequest = requests[i];
+
+ // keep the last data point per tick type
+ BaseData data = null;
+
+ if (historyRequest.DataType == typeof(QuoteBar))
+ {
+ if (slice.QuoteBars.TryGetValue(historyRequest.Symbol, out var quoteBar))
+ {
+ data = quoteBar;
+ }
+ }
+ else if (historyRequest.DataType == typeof(TradeBar))
+ {
+ if (slice.Bars.TryGetValue(historyRequest.Symbol, out var quoteBar))
+ {
+ data = quoteBar;
+ }
+ }
+ else if (historyRequest.DataType == typeof(OpenInterest))
+ {
+ if (slice.Ticks.TryGetValue(historyRequest.Symbol, out var openInterests))
+ {
+ data = openInterests[0];
+ }
+ }
+ // No Tick data, resolution is limited to Minute as minimum
+ else
+ {
+ var typeData = slice.Get(historyRequest.DataType);
+ if (typeData.ContainsKey(historyRequest.Symbol))
+ {
+ data = typeData[historyRequest.Symbol];
+ }
+ }
+
+ if (data != null)
+ {
+ result[(historyRequest.Symbol, historyRequest.DataType, historyRequest.TickType)] = data;
+ }
+ }
+ }
+
+ if (attempts < 2)
+ {
+ // Give it another try to get data for all symbols and all data types
+ GetLastKnownPricesImpl(null, result, attempts + 1,
+ requests.Where((request, i) => !result.ContainsKey((request.Symbol, request.DataType, request.TickType))));
+ }
+ }
+
///
/// Centralized logic to get data typed history given a list of requests for the specified symbol.
/// This method is used to keep backwards compatibility for those History methods that expect an ArgumentException to be thrown
@@ -990,7 +1118,7 @@ protected IEnumerable CreateDateRangeHistoryRequests(IEnumerable
///
private IEnumerable CreateBarCountHistoryRequests(IEnumerable symbols, int periods, Resolution? resolution = null,
bool? fillForward = null, bool? extendedMarketHours = null, DataMappingMode? dataMappingMode = null,
- DataNormalizationMode? dataNormalizationMode = null, int? contractDepthOffset = null)
+ DataNormalizationMode? dataNormalizationMode = null, int? contractDepthOffset = null, bool useAllSubscriptions = false)
{
// Materialize the symbols to avoid multiple enumeration
var symbolsArray = symbols.ToArray();
@@ -1003,7 +1131,8 @@ private IEnumerable CreateBarCountHistoryRequests(IEnumerable
@@ -1011,12 +1140,12 @@ private IEnumerable CreateBarCountHistoryRequests(IEnumerable
private IEnumerable CreateBarCountHistoryRequests(IEnumerable symbols, Type requestedType, int periods,
Resolution? resolution = null, bool? fillForward = null, bool? extendedMarketHours = null, DataMappingMode? dataMappingMode = null,
- DataNormalizationMode? dataNormalizationMode = null, int? contractDepthOffset = null)
+ DataNormalizationMode? dataNormalizationMode = null, int? contractDepthOffset = null, bool useAllSubscriptions = false)
{
return symbols.Where(HistoryRequestValid).SelectMany(symbol =>
{
// Match or create configs for the symbol
- var configs = GetMatchingSubscriptions(symbol, requestedType, resolution).ToList();
+ var configs = GetMatchingSubscriptions(symbol, requestedType, resolution, useAllSubscriptions).ToList();
if (configs.Count == 0)
{
return Enumerable.Empty();
@@ -1043,7 +1172,7 @@ private int GetTickTypeOrder(SecurityType securityType, TickType tickType)
return SubscriptionManager.AvailableDataTypes[securityType].IndexOf(tickType);
}
- private IEnumerable GetMatchingSubscriptions(Symbol symbol, Type type, Resolution? resolution = null)
+ private IEnumerable GetMatchingSubscriptions(Symbol symbol, Type type, Resolution? resolution = null, bool useAllSubscriptions = false)
{
var subscriptions = SubscriptionManager.SubscriptionDataConfigService
// we add internal subscription so that history requests are covered, this allows us to warm them up too
@@ -1068,7 +1197,7 @@ private IEnumerable GetMatchingSubscriptions(Symbol symb
else
{
// Filter subscriptions matching the requested type
- matchingSubscriptions = subscriptions.Where(s => SubscriptionDataConfigTypeFilter(type, s.Type));
+ matchingSubscriptions = subscriptions.Where(s => SubscriptionDataConfigTypeFilter(type, s.Type, filterOutOpenInterest: !useAllSubscriptions));
}
var internalConfig = new List();
@@ -1091,9 +1220,16 @@ private IEnumerable GetMatchingSubscriptions(Symbol symb
{
configs = userConfig;
}
- else if (internalConfig.Count != 0)
+ if ((useAllSubscriptions || configs == null) && internalConfig.Count != 0)
{
- configs = internalConfig;
+ if (configs == null)
+ {
+ configs = internalConfig;
+ }
+ else
+ {
+ configs.AddRange(internalConfig);
+ }
}
// we use the subscription manager registered configurations here, we can not rely on the Securities collection
@@ -1147,6 +1283,15 @@ private IEnumerable GetMatchingSubscriptions(Symbol symb
}
else
{
+ // let's try to respect already added user settings, even if resolution/type don't match, like Tick vs Bars
+ var userConfigIfAny = subscriptions.FirstOrDefault(x => LeanData.IsCommonLeanDataType(x.Type) && !x.IsInternalFeed);
+
+ // Inherit values from existing subscriptions or use defaults
+ var extendedMarketHours = userConfigIfAny?.ExtendedMarketHours ?? UniverseSettings.ExtendedMarketHours;
+ var dataNormalizationMode = userConfigIfAny?.DataNormalizationMode ?? UniverseSettings.GetUniverseNormalizationModeOrDefault(symbol.SecurityType);
+ var dataMappingMode = userConfigIfAny?.DataMappingMode ?? UniverseSettings.GetUniverseMappingModeOrDefault(symbol.SecurityType, symbol.ID.Market);
+ var contractDepthOffset = userConfigIfAny?.ContractDepthOffset ?? (uint)Math.Abs(UniverseSettings.ContractDepthOffset);
+
// If type was specified and not a lean data type and also not abstract, we create a new subscription
if (type != null && !LeanData.IsCommonLeanDataType(type) && !type.IsAbstract)
{
@@ -1170,23 +1315,22 @@ private IEnumerable GetMatchingSubscriptions(Symbol symb
entry.DataTimeZone,
entry.ExchangeHours.TimeZone,
UniverseSettings.FillForward,
- UniverseSettings.ExtendedMarketHours,
+ extendedMarketHours,
true,
isCustom,
LeanData.GetCommonTickTypeForCommonDataTypes(dataType, symbol.SecurityType),
true,
- UniverseSettings.GetUniverseNormalizationModeOrDefault(symbol.SecurityType))};
+ dataNormalizationMode,
+ dataMappingMode,
+ contractDepthOffset)};
}
- // let's try to respect already added user settings, even if resolution/type don't match, like Tick vs Bars
- var userConfigIfAny = subscriptions.FirstOrDefault(x => LeanData.IsCommonLeanDataType(x.Type) && !x.IsInternalFeed);
-
var res = GetResolution(symbol, resolution, type);
return SubscriptionManager
.LookupSubscriptionConfigDataTypes(symbol.SecurityType, res,
// for continuous contracts, if we are given a type (or none) that's common (like trade/quote), we respect it
symbol.IsCanonical() && (symbol.SecurityType != SecurityType.Future || type != null && !LeanData.IsCommonLeanDataType(type)))
- .Where(tuple => SubscriptionDataConfigTypeFilter(type, tuple.Item1))
+ .Where(tuple => SubscriptionDataConfigTypeFilter(type, tuple.Item1, filterOutOpenInterest: !useAllSubscriptions))
.Select(x =>
{
var configType = x.Item1;
@@ -1201,14 +1345,14 @@ private IEnumerable GetMatchingSubscriptions(Symbol symb
entry.DataTimeZone,
entry.ExchangeHours.TimeZone,
UniverseSettings.FillForward,
- userConfigIfAny?.ExtendedMarketHours ?? UniverseSettings.ExtendedMarketHours,
+ extendedMarketHours,
true,
false,
x.Item2,
true,
- userConfigIfAny?.DataNormalizationMode ?? UniverseSettings.GetUniverseNormalizationModeOrDefault(symbol.SecurityType),
- userConfigIfAny?.DataMappingMode ?? UniverseSettings.GetUniverseMappingModeOrDefault(symbol.SecurityType, symbol.ID.Market),
- userConfigIfAny?.ContractDepthOffset ?? (uint)Math.Abs(UniverseSettings.ContractDepthOffset));
+ dataNormalizationMode,
+ dataMappingMode,
+ contractDepthOffset);
})
// lets make sure to respect the order of the data types, if used on a history request will affect outcome when using pushthrough for example
.OrderByDescending(config => GetTickTypeOrder(config.SecurityType, config.TickType));
@@ -1220,16 +1364,16 @@ private IEnumerable GetMatchingSubscriptions(Symbol symb
///
/// If the target type is , config types will return false.
/// This is useful to filter OpenInterest by default from history requests unless it's explicitly requested
- private bool SubscriptionDataConfigTypeFilter(Type targetType, Type configType)
+ private bool SubscriptionDataConfigTypeFilter(Type targetType, Type configType, bool filterOutOpenInterest = true)
{
if (targetType == null)
{
- return configType != typeof(OpenInterest);
+ return !filterOutOpenInterest || configType != typeof(OpenInterest);
}
var targetIsGenericType = targetType == typeof(BaseData);
- return targetType.IsAssignableFrom(configType) && (!targetIsGenericType || configType != typeof(OpenInterest));
+ return targetType.IsAssignableFrom(configType) && (!targetIsGenericType || !filterOutOpenInterest || configType != typeof(OpenInterest));
}
private SecurityExchangeHours GetExchangeHours(Symbol symbol, Type type = null)
diff --git a/Algorithm/QCAlgorithm.Indicators.cs b/Algorithm/QCAlgorithm.Indicators.cs
index adae8e3107f9..2662f7de3eeb 100644
--- a/Algorithm/QCAlgorithm.Indicators.cs
+++ b/Algorithm/QCAlgorithm.Indicators.cs
@@ -53,7 +53,8 @@ public partial class QCAlgorithm
"IsReady",
"Window",
"Item",
- "WarmUpPeriod"
+ "WarmUpPeriod",
+ "Period"
};
///
@@ -489,6 +490,26 @@ public Correlation C(Symbol target, Symbol reference, int period, CorrelationTyp
return correlation;
}
+ ///
+ /// Creates a Covariance indicator for the given target symbol in relation with the reference used.
+ /// The indicator will be automatically updated on the given resolution.
+ ///
+ /// The target symbol whose Covariance value we want
+ /// The reference symbol to compare with the target symbol
+ /// The period of the Covariance indicator
+ /// The resolution
+ /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar
+ /// The Covariance indicator for the given parameters
+ [DocumentationAttribute(Indicators)]
+ public Covariance COV(Symbol target, Symbol reference, int period, Resolution? resolution = null, Func selector = null)
+ {
+ var name = CreateIndicatorName(QuantConnect.Symbol.None, $"COV({period})", resolution);
+ var covariance = new Covariance(name, target, reference, period);
+ InitializeIndicator(covariance, resolution, selector, target, reference);
+
+ return covariance;
+ }
+
///
/// Creates a new CommodityChannelIndex indicator. The indicator will be automatically
/// updated on the given resolution.
@@ -1435,7 +1456,7 @@ public MesaAdaptiveMovingAverage MAMA(Symbol symbol, decimal fastLimit = 0.5m, d
[DocumentationAttribute(Indicators)]
public VolumeProfile VP(Symbol symbol, int period = 2, decimal valueAreaVolumePercentage = 0.70m, decimal priceRangeRoundOff = 0.05m, Resolution resolution = Resolution.Daily, Func selector = null)
{
- var name = CreateIndicatorName(symbol, $"VP({period})", resolution);
+ var name = CreateIndicatorName(symbol, $"VP({period},{valueAreaVolumePercentage},{priceRangeRoundOff})", resolution);
var marketProfile = new VolumeProfile(name, period, valueAreaVolumePercentage, priceRangeRoundOff);
InitializeIndicator(marketProfile, resolution, selector, symbol);
@@ -1456,7 +1477,7 @@ public VolumeProfile VP(Symbol symbol, int period = 2, decimal valueAreaVolumePe
[DocumentationAttribute(Indicators)]
public TimeProfile TP(Symbol symbol, int period = 2, decimal valueAreaVolumePercentage = 0.70m, decimal priceRangeRoundOff = 0.05m, Resolution resolution = Resolution.Daily, Func selector = null)
{
- var name = CreateIndicatorName(symbol, $"TP({period})", resolution);
+ var name = CreateIndicatorName(symbol, $"TP({period},{valueAreaVolumePercentage},{priceRangeRoundOff})", resolution);
var marketProfile = new TimeProfile(name, period, valueAreaVolumePercentage, priceRangeRoundOff);
InitializeIndicator(marketProfile, resolution, selector, symbol);
@@ -1691,6 +1712,50 @@ public NormalizedAverageTrueRange NATR(Symbol symbol, int period, Resolution? re
return normalizedAverageTrueRange;
}
+ ///
+ /// Creates a new New Highs - New Lows indicator
+ ///
+ /// The symbols whose NHNL we want
+ /// The period over which to compute the NHNL
+ /// The resolution
+ /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a IBaseDataBar
+ /// The NewHighsNewLows indicator for the requested symbols over the specified period
+ [DocumentationAttribute(Indicators)]
+ public NewHighsNewLows NHNL(IEnumerable symbols, int period, Resolution? resolution = null, Func selector = null)
+ {
+ var name = CreateIndicatorName(QuantConnect.Symbol.None, $"NH/NL({period})", resolution ?? GetSubscription(symbols.First()).Resolution);
+ var nhnlDifference = new NewHighsNewLows(name, period);
+ foreach (var symbol in symbols)
+ {
+ nhnlDifference.Add(symbol);
+ }
+ InitializeIndicator(nhnlDifference, resolution, selector, symbols.ToArray());
+
+ return nhnlDifference;
+ }
+
+ ///
+ /// Creates a new New Highs - New Lows Volume indicator
+ ///
+ /// The symbols whose NHNLV we want
+ /// The period over which to compute the NHNLV
+ /// The resolution
+ /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar
+ /// The NewHighsNewLowsVolume indicator for the requested symbols over the specified period
+ [DocumentationAttribute(Indicators)]
+ public NewHighsNewLowsVolume NHNLV(IEnumerable symbols, int period, Resolution? resolution = null, Func selector = null)
+ {
+ var name = CreateIndicatorName(QuantConnect.Symbol.None, $"NH/NL Volume({period})", resolution ?? GetSubscription(symbols.First()).Resolution);
+ var nhnlVolume = new NewHighsNewLowsVolume(name, period);
+ foreach (var symbol in symbols)
+ {
+ nhnlVolume.Add(symbol);
+ }
+ InitializeIndicator(nhnlVolume, resolution, selector, symbols.ToArray());
+
+ return nhnlVolume;
+ }
+
///
/// Creates a new On Balance Volume indicator. This will compute the cumulative total volume
/// based on whether the close price being higher or lower than the previous period.
@@ -2215,7 +2280,7 @@ public TargetDownsideDeviation TDD(Symbol symbol, int period, double minimumAcce
return targetDownsideDeviation;
}
-
+
///
/// Creates a new TomDemark Sequential candlestick indicator for the symbol. The indicator will be automatically
/// updated on the symbol's subscription resolution.
diff --git a/Algorithm/QCAlgorithm.Plotting.cs b/Algorithm/QCAlgorithm.Plotting.cs
index 23abbae02a4f..a8c68999dd4b 100644
--- a/Algorithm/QCAlgorithm.Plotting.cs
+++ b/Algorithm/QCAlgorithm.Plotting.cs
@@ -497,6 +497,12 @@ public void SetRuntimeStatistic(string name, double value)
[DocumentationAttribute(StatisticsTag)]
public void SetSummaryStatistic(string name, string value)
{
+ if (int.TryParse(name, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intName) &&
+ intName >= 0 && intName <= 100)
+ {
+ throw new ArgumentException($"'{name}' is a reserved statistic name.");
+ }
+
_statisticsService.SetSummaryStatistic(name, value);
}
@@ -508,7 +514,7 @@ public void SetSummaryStatistic(string name, string value)
[DocumentationAttribute(StatisticsTag)]
public void SetSummaryStatistic(string name, int value)
{
- _statisticsService.SetSummaryStatistic(name, value.ToStringInvariant());
+ SetSummaryStatistic(name, value.ToStringInvariant());
}
///
@@ -519,7 +525,7 @@ public void SetSummaryStatistic(string name, int value)
[DocumentationAttribute(StatisticsTag)]
public void SetSummaryStatistic(string name, double value)
{
- _statisticsService.SetSummaryStatistic(name, value.ToStringInvariant());
+ SetSummaryStatistic(name, value.ToStringInvariant());
}
///
@@ -530,7 +536,7 @@ public void SetSummaryStatistic(string name, double value)
[DocumentationAttribute(StatisticsTag)]
public void SetSummaryStatistic(string name, decimal value)
{
- _statisticsService.SetSummaryStatistic(name, value.ToStringInvariant());
+ SetSummaryStatistic(name, value.ToStringInvariant());
}
///
diff --git a/Algorithm/QCAlgorithm.Python.cs b/Algorithm/QCAlgorithm.Python.cs
index 8d1fbb94e678..a2af01ea34fc 100644
--- a/Algorithm/QCAlgorithm.Python.cs
+++ b/Algorithm/QCAlgorithm.Python.cs
@@ -1372,12 +1372,10 @@ public void SetBenchmark(PyObject benchmark)
[DocumentationAttribute(Modeling)]
public void SetBrokerageModel(PyObject model)
{
- IBrokerageModel brokerageModel;
- if (!model.TryConvert(out brokerageModel))
- {
- brokerageModel = new BrokerageModelPythonWrapper(model);
- }
-
+ var brokerageModel = PythonUtil.CreateInstanceOrWrapper(
+ model,
+ py => new BrokerageModelPythonWrapper(py)
+ );
SetBrokerageModel(brokerageModel);
}
@@ -1392,11 +1390,10 @@ public void SetBrokerageModel(PyObject model)
[DocumentationAttribute(Logging)]
public void SetBrokerageMessageHandler(PyObject handler)
{
- if (!handler.TryConvert(out IBrokerageMessageHandler brokerageMessageHandler))
- {
- brokerageMessageHandler = new BrokerageMessageHandlerPythonWrapper(handler);
- }
-
+ var brokerageMessageHandler = PythonUtil.CreateInstanceOrWrapper(
+ handler,
+ py => new BrokerageMessageHandlerPythonWrapper(py)
+ );
SetBrokerageMessageHandler(brokerageMessageHandler);
}
@@ -1407,7 +1404,11 @@ public void SetBrokerageMessageHandler(PyObject handler)
[DocumentationAttribute(Modeling)]
public void SetRiskFreeInterestRateModel(PyObject model)
{
- SetRiskFreeInterestRateModel(RiskFreeInterestRateModelPythonWrapper.FromPyObject(model));
+ var riskFreeInterestRateModel = PythonUtil.CreateInstanceOrWrapper(
+ model,
+ py => new RiskFreeInterestRateModelPythonWrapper(py)
+ );
+ SetRiskFreeInterestRateModel(riskFreeInterestRateModel);
}
///
diff --git a/Algorithm/QCAlgorithm.Universe.cs b/Algorithm/QCAlgorithm.Universe.cs
index 8dac58fd2d71..3f249e067498 100644
--- a/Algorithm/QCAlgorithm.Universe.cs
+++ b/Algorithm/QCAlgorithm.Universe.cs
@@ -16,6 +16,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Collections.Specialized;
using NodaTime;
using QuantConnect.Algorithm.Selection;
using QuantConnect.Data;
@@ -33,7 +34,7 @@ public partial class QCAlgorithm
// this removes temporal dependencies from w/in initialize method
// original motivation: adding equity/options to enforce equity raw data mode
private readonly object _pendingUniverseAdditionsLock = new object();
- private readonly List _pendingUserDefinedUniverseSecurityAdditions = new List();
+ private readonly List _pendingUserDefinedUniverseSecurityChanges = new();
private bool _pendingUniverseAdditions;
private ConcurrentSet _rawNormalizationWarningSymbols = new ConcurrentSet();
private readonly int _rawNormalizationWarningSymbolsMaxCount = 10;
@@ -69,16 +70,16 @@ public void OnEndOfTimeStep()
// rewrite securities w/ derivatives to be in raw mode
lock (_pendingUniverseAdditionsLock)
{
- if (!_pendingUniverseAdditions && _pendingUserDefinedUniverseSecurityAdditions.Count == 0)
+ if (!_pendingUniverseAdditions && _pendingUserDefinedUniverseSecurityChanges.Count == 0)
{
// no point in looping through everything if there's no pending changes
return;
}
- var requiredHistoryRequests = new Dictionary();
+ var securitiesToSeed = new HashSet();
foreach (var security in Securities.Select(kvp => kvp.Value).Union(
- _pendingUserDefinedUniverseSecurityAdditions.Select(x => x.Security)))
+ _pendingUserDefinedUniverseSecurityChanges.Where(x => x.IsAddition).Select(x => x.Security)))
{
// check for any derivative securities and mark the underlying as raw
if (security.Type == SecurityType.Equity &&
@@ -123,22 +124,9 @@ public void OnEndOfTimeStep()
ConfigureUnderlyingSecurity(underlyingSecurity);
}
- if (LiveMode && underlyingSecurity.GetLastData() == null)
+ if (LiveMode && !Settings.SeedInitialPrices && underlyingSecurity.GetLastData() == null)
{
- if (requiredHistoryRequests.ContainsKey(underlyingSecurity))
- {
- // lets request the higher resolution
- var currentResolutionRequest = requiredHistoryRequests[underlyingSecurity];
- if (currentResolutionRequest != Resolution.Minute // Can not be less than Minute
- && resolution < currentResolutionRequest)
- {
- requiredHistoryRequests[underlyingSecurity] = (Resolution)Math.Max((int)resolution, (int)Resolution.Minute);
- }
- }
- else
- {
- requiredHistoryRequests.Add(underlyingSecurity, (Resolution)Math.Max((int)resolution, (int)Resolution.Minute));
- }
+ securitiesToSeed.Add(underlyingSecurity);
}
// set the underlying security on the derivative -- we do this in two places since it's possible
// to do AddOptionContract w/out the underlying already added and normalized properly
@@ -150,30 +138,32 @@ public void OnEndOfTimeStep()
}
}
- if (!requiredHistoryRequests.IsNullOrEmpty())
+ if (!securitiesToSeed.IsNullOrEmpty())
{
- // Create requests
- var historyRequests = Enumerable.Empty();
- foreach (var byResolution in requiredHistoryRequests.GroupBy(x => x.Value))
- {
- historyRequests = historyRequests.Concat(
- CreateBarCountHistoryRequests(byResolution.Select(x => x.Key.Symbol), 3, byResolution.Key));
- }
- // Request data
- var historicLastData = History(historyRequests);
- historicLastData.PushThrough(x =>
- {
- var security = requiredHistoryRequests.Keys.FirstOrDefault(y => y.Symbol == x.Symbol);
- security?.Cache.AddData(x);
- });
+ AlgorithmUtils.SeedSecurities(securitiesToSeed, this);
}
// add subscriptionDataConfig to their respective user defined universes
- foreach (var userDefinedUniverseAddition in _pendingUserDefinedUniverseSecurityAdditions)
+ foreach (var userDefinedUniverseAddition in _pendingUserDefinedUniverseSecurityChanges)
{
- foreach (var subscriptionDataConfig in userDefinedUniverseAddition.SubscriptionDataConfigs)
+ var changedCollection = false;
+ var action = NotifyCollectionChangedAction.Add;
+ if (userDefinedUniverseAddition.IsAddition)
+ {
+ foreach (var subscriptionDataConfig in userDefinedUniverseAddition.SubscriptionDataConfigs)
+ {
+ changedCollection |= userDefinedUniverseAddition.Universe.Add(subscriptionDataConfig);
+ }
+ }
+ else
+ {
+ action = NotifyCollectionChangedAction.Replace;
+ changedCollection |= userDefinedUniverseAddition.Universe.Remove(userDefinedUniverseAddition.Security);
+ }
+
+ if (changedCollection)
{
- userDefinedUniverseAddition.Universe.Add(subscriptionDataConfig);
+ UniverseManager.Update(userDefinedUniverseAddition.Universe.Symbol, userDefinedUniverseAddition.Universe, action);
}
}
@@ -183,7 +173,7 @@ public void OnEndOfTimeStep()
UniverseManager.ProcessChanges();
_pendingUniverseAdditions = false;
- _pendingUserDefinedUniverseSecurityAdditions.Clear();
+ _pendingUserDefinedUniverseSecurityChanges.Clear();
}
if (!_rawNormalizationWarningSymbols.IsNullOrEmpty())
@@ -645,8 +635,7 @@ private Security AddToUserDefinedUniverse(
{
lock (_pendingUniverseAdditionsLock)
{
- _pendingUserDefinedUniverseSecurityAdditions.Add(
- new UserDefinedUniverseAddition(userDefinedUniverse, configurations, security));
+ _pendingUserDefinedUniverseSecurityChanges.Add(new UserDefinedUniverseUpdate(userDefinedUniverse, configurations, security));
}
}
else
@@ -743,13 +732,14 @@ private Universe AddUniverseSymbolSelector(Type dataType, string name = null, Re
/// Helper class used to store additions.
/// They will be consumed at
///
- private class UserDefinedUniverseAddition
+ private class UserDefinedUniverseUpdate
{
+ public bool IsAddition => SubscriptionDataConfigs != null;
public Security Security { get; }
public UserDefinedUniverse Universe { get; }
public List SubscriptionDataConfigs { get; }
- public UserDefinedUniverseAddition(
+ public UserDefinedUniverseUpdate(
UserDefinedUniverse universe,
List subscriptionDataConfigs,
Security security)
diff --git a/Algorithm/QCAlgorithm.cs b/Algorithm/QCAlgorithm.cs
index 6d7aafd186b7..7c383f0c072d 100644
--- a/Algorithm/QCAlgorithm.cs
+++ b/Algorithm/QCAlgorithm.cs
@@ -58,6 +58,7 @@
using Newtonsoft.Json;
using QuantConnect.Securities.Index;
using QuantConnect.Api;
+using Common.Util;
namespace QuantConnect.Algorithm
{
@@ -256,7 +257,7 @@ public QCAlgorithm()
public event AlgorithmEvent InsightsGenerated;
///
- /// Security collection is an array of the security objects such as Equities and FOREX. Securities data
+ /// Security collection is an array of the security objects such as and . Securities data
/// manages the properties of tradeable assets such as price, open and close time and holdings information.
///
[DocumentationAttribute(SecuritiesAndPortfolio)]
@@ -271,7 +272,7 @@ public SecurityManager Securities
/// a security that is currently selected by the universe or has holdings or open orders.
///
[DocumentationAttribute(SecuritiesAndPortfolio)]
- public IReadOnlyDictionary ActiveSecurities => UniverseManager.ActiveSecurities;
+ public ReadOnlyExtendedDictionary ActiveSecurities => UniverseManager.ActiveSecurities;
///
/// Portfolio object provieds easy access to the underlying security-holding properties; summed together in a way to make them useful.
@@ -839,11 +840,6 @@ public virtual void PostInitialize()
SetFinishedWarmingUp();
}
- if (Settings.DailyPreciseEndTime)
- {
- Debug("Accurate daily end-times now enabled by default. See more at https://qnt.co/3YHaWHL. To disable it and use legacy daily bars set self.settings.daily_precise_end_time = False.");
- }
-
// perform end of time step checks, such as enforcing underlying securities are in raw data mode
OnEndOfTimeStep();
}
@@ -914,9 +910,9 @@ public decimal GetParameter(string name, decimal defaultValue)
/// Gets a read-only dictionary with all current parameters
///
[DocumentationAttribute(ParameterAndOptimization)]
- public IReadOnlyDictionary GetParameters()
+ public ReadOnlyExtendedDictionary GetParameters()
{
- return _parameters.ToReadOnlyDictionary();
+ return _parameters.ToReadOnlyExtendedDictionary();
}
///
@@ -1247,6 +1243,7 @@ public virtual void OnAssignmentOrderEvent(OrderEvent assignmentEvent)
///
/// Brokerage message event handler. This method is called for all types of brokerage messages.
///
+ /// The brokerage message event instance containing the message details.
[DocumentationAttribute(LiveTrading)]
[DocumentationAttribute(Modeling)]
[DocumentationAttribute(TradingAndOrders)]
@@ -1440,7 +1437,7 @@ public void SetRiskFreeInterestRateModel(IRiskFreeInterestRateModel model)
/// Sets the benchmark used for computing statistics of the algorithm to the specified symbol
///
/// symbol to use as the benchmark
- /// Is the symbol an equity, forex, base, etc. Default SecurityType.Equity
+ /// Is the symbol an equity, forex, base, etc. Default
///
/// Must use symbol that is available to the trade engine in your data store(not strictly enforced)
///
@@ -1462,12 +1459,12 @@ public void SetBenchmark(SecurityType securityType, string symbol)
}
///
- /// Sets the benchmark used for computing statistics of the algorithm to the specified ticker, defaulting to SecurityType.Equity
+ /// Sets the benchmark used for computing statistics of the algorithm to the specified ticker, defaulting to
/// if the ticker doesn't exist in the algorithm
///
/// Ticker to use as the benchmark
///
- /// Overload to accept ticker without passing SecurityType. If ticker is in portfolio it will use that SecurityType, otherwise will default to SecurityType.Equity
+ /// Overload to accept ticker without passing . If ticker is in portfolio it will use that , otherwise will default to
///
[DocumentationAttribute(TradingAndOrders)]
[DocumentationAttribute(SecuritiesAndPortfolio)]
@@ -1531,9 +1528,9 @@ public void SetBenchmark(Func benchmark)
}
///
- /// Benchmark
+ /// The for the algorithm
///
- /// Use Benchmark to override default symbol based benchmark, and create your own benchmark. For example a custom moving average benchmark
+ /// Use for the algorithm to override default symbol based benchmark, and create your own benchmark. For example a custom moving average benchmark
///
[DocumentationAttribute(TradingAndOrders)]
[DocumentationAttribute(SecuritiesAndPortfolio)]
@@ -1622,7 +1619,7 @@ public void SetAccountCurrency(string accountCurrency, decimal? startingCash = n
/// and replaced with the actual cash of your brokerage account.
///
/// Starting cash for the strategy backtest
- /// Alias of SetCash(decimal)
+ /// Alias of
[DocumentationAttribute(SecuritiesAndPortfolio)]
public void SetCash(double startingCash)
{
@@ -1634,7 +1631,7 @@ public void SetCash(double startingCash)
/// and replaced with the actual cash of your brokerage account.
///
/// Starting cash for the strategy backtest
- /// Alias of SetCash(decimal)
+ /// Alias of
[DocumentationAttribute(SecuritiesAndPortfolio)]
public void SetCash(int startingCash)
{
@@ -1746,7 +1743,7 @@ public void SetAlgorithmId(string algorithmId)
///
/// Set the start date for the backtest
///
- /// Datetime Start date for backtest
+ /// The start date for the backtest
/// Must be less than end date and within data available
///
[DocumentationAttribute(HandlingData)]
@@ -2148,7 +2145,7 @@ public Option AddOption(string underlying, Resolution? resolution = null, string
///
/// Underlying asset Symbol to use as the option's underlying
/// The of market data, Tick, Second, Minute, Hour, or Daily. Default is
- /// The option's market, . Default value is null, but will be resolved using BrokerageModel.DefaultMarkets in
+ /// The option's market, . Default value is null, but will be resolved using in
/// If true, data will be provided to the algorithm every Second, Minute, Hour, or Day, while the asset is open and depending on the Resolution this option was configured to use.
/// The requested leverage for the
/// The new option security instance
@@ -2167,7 +2164,7 @@ public Option AddOption(Symbol underlying, Resolution? resolution = null, string
/// Underlying asset Symbol to use as the option's underlying
/// The target option ticker. This is useful when the option ticker does not match the underlying, e.g. SPX index and the SPXW weekly option. If null is provided will use underlying
/// The of market data, Tick, Second, Minute, Hour, or Daily. Default is
- /// The option's market, . Default value is null, but will be resolved using BrokerageModel.DefaultMarkets in
+ /// The option's market, . Default value is null, but will be resolved using in
/// If true, data will be provided to the algorithm every Second, Minute, Hour, or Day, while the asset is open and depending on the Resolution this option was configured to use.
/// The requested leverage for the
/// The new option security instance
@@ -2206,9 +2203,9 @@ public Option AddOption(Symbol underlying, string targetOption, Resolution? reso
///
/// The future ticker
/// The of market data, Tick, Second, Minute, Hour, or Daily. Default is
- /// The futures market, . Default is value null and looked up using BrokerageModel.DefaultMarkets in
+ /// The futures market, . Default is value null and looked up using in
/// If true, returns the last available data even if none in that timeslice. Default is true
- /// The requested leverage for this equity. Default is set by
+ /// The requested leverage for this future. Default is set by
/// Use extended market hours data
/// The contract mapping mode to use for the continuous future contract
/// The price scaling mode to use for the continuous future contract
@@ -2241,7 +2238,7 @@ public Future AddFuture(string ticker, Resolution? resolution = null, string mar
/// The futures contract symbol
/// The of market data, Tick, Second, Minute, Hour, or Daily. Default is
/// If true, returns the last available data even if none in that timeslice. Default is true
- /// The requested leverage for this equity. Default is set by
+ /// The requested leverage for this future. Default is set by
/// Use extended market hours data
/// The new security
[DocumentationAttribute(AddingData)]
@@ -2301,12 +2298,13 @@ public Option AddFutureOptionContract(Symbol symbol, Resolution? resolution = nu
///
/// Creates and adds index options to the algorithm.
///
- /// The underlying ticker of the Index Option
+ /// The underlying ticker of the
/// Resolution of the index option contracts, i.e. the granularity of the data
- /// The foreign exchange trading market, . Default value is null and looked up using BrokerageModel.DefaultMarkets in
+ /// The foreign exchange trading market, . Default value is null and looked up using in
/// If true, this will fill in missing data points with the previous data point
/// Canonical Option security
[DocumentationAttribute(AddingData)]
+
public IndexOption AddIndexOption(string underlying, Resolution? resolution = null, string market = null, bool fillForward = true)
{
return AddIndexOption(underlying, null, resolution, market, fillForward);
@@ -2350,7 +2348,7 @@ public IndexOption AddIndexOption(Symbol symbol, string targetOption, Resolution
/// The underlying ticker of the Index Option
/// The target option ticker. This is useful when the option ticker does not match the underlying, e.g. SPX index and the SPXW weekly option. If null is provided will use underlying
/// Resolution of the index option contracts, i.e. the granularity of the data
- /// The foreign exchange trading market, . Default value is null and looked up using BrokerageModel.DefaultMarkets in
+ /// The foreign exchange trading market, . Default value is null and looked up using in
/// If true, this will fill in missing data points with the previous data point
/// Canonical Option security
[DocumentationAttribute(AddingData)]
@@ -2368,7 +2366,7 @@ public IndexOption AddIndexOption(string underlying, string targetOption, Resolu
/// Resolution of the index option contract, i.e. the granularity of the data
/// If true, this will fill in missing data points with the previous data point
/// Index Option Contract
- /// The provided Symbol is not an Index Option
+ /// The provided Symbol is not an
[DocumentationAttribute(AddingData)]
public IndexOption AddIndexOptionContract(Symbol symbol, Resolution? resolution = null, bool fillForward = true)
{
@@ -2386,7 +2384,7 @@ public IndexOption AddIndexOptionContract(Symbol symbol, Resolution? resolution
/// The option contract symbol
/// The of market data, Tick, Second, Minute, Hour, or Daily. Default is
/// If true, returns the last available data even if none in that timeslice. Default is true
- /// The requested leverage for this equity. Default is set by
+ /// The requested leverage for this option. Default is set by
/// Use extended market hours data
/// The new security
[DocumentationAttribute(AddingData)]
@@ -2467,9 +2465,9 @@ public Option AddOptionContract(Symbol symbol, Resolution? resolution = null, bo
var optionUniverse = universe as OptionContractUniverse;
if (optionUniverse != null)
{
- foreach (var subscriptionDataConfig in configs.Concat(underlyingConfigs))
+ lock (_pendingUniverseAdditionsLock)
{
- optionUniverse.Add(subscriptionDataConfig);
+ _pendingUserDefinedUniverseSecurityChanges.Add(new UserDefinedUniverseUpdate(optionUniverse, [.. configs, .. underlyingConfigs], option));
}
}
@@ -2481,9 +2479,9 @@ public Option AddOptionContract(Symbol symbol, Resolution? resolution = null, bo
///
/// The currency pair
/// The of market data, Tick, Second, Minute, Hour, or Daily. Default is
- /// The foreign exchange trading market, . Default value is null and looked up using BrokerageModel.DefaultMarkets in
+ /// The foreign exchange trading market, . Default value is null and looked up using in
/// If true, returns the last available data even if none in that timeslice. Default is true
- /// The requested leverage for this equity. Default is set by
+ /// The requested leverage for this forex security. Default is set by
/// The new security
[DocumentationAttribute(AddingData)]
public Forex AddForex(string ticker, Resolution? resolution = null, string market = null, bool fillForward = true, decimal leverage = Security.NullLeverage)
@@ -2494,11 +2492,11 @@ public Forex AddForex(string ticker, Resolution? resolution = null, string marke
///
/// Creates and adds a new security to the algorithm
///
- /// The currency pair
+ /// The CFD ticker symbol
/// The of market data, Tick, Second, Minute, Hour, or Daily. Default is
- /// The cfd trading market, . Default value is null and looked up using BrokerageModel.DefaultMarkets in
+ /// The cfd trading market, . Default value is null and looked up using in
/// If true, returns the last available data even if none in that timeslice. Default is true
- /// The requested leverage for this equity. Default is set by
+ /// The requested leverage for this CFD. Default is set by
/// The new security
[DocumentationAttribute(AddingData)]
public Cfd AddCfd(string ticker, Resolution? resolution = null, string market = null, bool fillForward = true, decimal leverage = Security.NullLeverage)
@@ -2510,9 +2508,9 @@ public Cfd AddCfd(string ticker, Resolution? resolution = null, string market =
///
/// Creates and adds a new security to the algorithm
///
- /// The currency pair
+ /// The index ticker
/// The of market data, Tick, Second, Minute, Hour, or Daily. Default is
- /// The index trading market, . Default value is null and looked up using BrokerageModel.DefaultMarkets in
+ /// The index trading market, . Default value is null and looked up using in
/// If true, returns the last available data even if none in that timeslice. Default is true
/// The new security
[DocumentationAttribute(AddingData)]
@@ -2525,11 +2523,11 @@ public Index AddIndex(string ticker, Resolution? resolution = null, string marke
///
/// Creates and adds a new security to the algorithm
///
- /// The currency pair
+ /// The crypto ticker symbol/param>
/// The of market data, Tick, Second, Minute, Hour, or Daily. Default is
- /// The cfd trading market, . Default value is null and looked up using BrokerageModel.DefaultMarkets in
+ /// The The crypto trading market, . Default value is null and looked up using in
/// If true, returns the last available data even if none in that timeslice. Default is true
- /// The requested leverage for this equity. Default is set by
+ /// The requested leverage for this crypto. Default is set by
/// The new security
[DocumentationAttribute(AddingData)]
public Crypto AddCrypto(string ticker, Resolution? resolution = null, string market = null, bool fillForward = true, decimal leverage = Security.NullLeverage)
@@ -2540,11 +2538,11 @@ public Crypto AddCrypto(string ticker, Resolution? resolution = null, string mar
///
/// Creates and adds a new security to the algorithm
///
- /// The currency pair
+ /// The crypto future ticker symbol
/// The of market data, Tick, Second, Minute, Hour, or Daily. Default is
- /// The cfd trading market, . Default value is null and looked up using BrokerageModel.DefaultMarkets in
+ /// The The crypto future trading market, . Default value is null and looked up using in
/// If true, returns the last available data even if none in that timeslice. Default is true
- /// The requested leverage for this equity. Default is set by
+ /// The requested leverage for this crypto future. Default is set by
/// The new security
[DocumentationAttribute(AddingData)]
public CryptoFuture AddCryptoFuture(string ticker, Resolution? resolution = null, string market = null, bool fillForward = true, decimal leverage = Security.NullLeverage)
@@ -2558,7 +2556,7 @@ public CryptoFuture AddCryptoFuture(string ticker, Resolution? resolution = null
///
/// The symbol of the security to be removed
/// Optional tag to indicate the cause of removal
- /// Sugar syntax for
+ /// Sugar syntax for
[DocumentationAttribute(AddingData)]
public bool RemoveOptionContract(Symbol symbol, string tag = null)
{
@@ -2632,14 +2630,15 @@ public bool RemoveSecurity(Symbol symbol, string tag = null)
{
lock (_pendingUniverseAdditionsLock)
{
+ // for existing universes we need to purge pending additions too, also handled at OnEndOfTimeStep()
+ _pendingUserDefinedUniverseSecurityChanges.RemoveAll(addition => addition.Security.Symbol == symbol);
+
// we need to handle existing universes and pending to be added universes, that will be pushed
// at the end of this time step see OnEndOfTimeStep()
- foreach (var universe in UniverseManager.Select(x => x.Value).OfType())
+ foreach (var universe in UniverseManager.Where(x => x.Value.ContainsMember(security)).Select(x => x.Value).OfType())
{
- universe.Remove(symbol);
+ _pendingUserDefinedUniverseSecurityChanges.Add(new UserDefinedUniverseUpdate(universe, null, security));
}
- // for existing universes we need to purge pending additions too, also handled at OnEndOfTimeStep()
- _pendingUserDefinedUniverseSecurityAdditions.RemoveAll(addition => addition.Security.Symbol == symbol);
}
}
return true;
@@ -2787,7 +2786,7 @@ public Security AddData(string ticker, SymbolProperties properties, SecurityE
public void Debug(string message)
{
if (!_liveMode && (string.IsNullOrEmpty(message) || _previousDebugMessage == message)) return;
- _debugMessages.Enqueue(message);
+ _debugMessages.Enqueue(FormatLog(message));
_previousDebugMessage = message;
}
@@ -2837,7 +2836,7 @@ public void Debug(decimal message)
public void Log(string message)
{
if (!_liveMode && string.IsNullOrEmpty(message)) return;
- _logMessages.Enqueue(message);
+ _logMessages.Enqueue(FormatLog(message));
}
///
@@ -2886,7 +2885,7 @@ public void Log(decimal message)
public void Error(string message)
{
if (!_liveMode && (string.IsNullOrEmpty(message) || _previousErrorMessage == message)) return;
- _errorMessages.Enqueue(message);
+ _errorMessages.Enqueue(FormatLog(message));
_previousErrorMessage = message;
}
@@ -2935,10 +2934,7 @@ public void Error(decimal message)
[DocumentationAttribute(Logging)]
public void Error(Exception error)
{
- var message = error.Message;
- if (!_liveMode && (string.IsNullOrEmpty(message) || _previousErrorMessage == message)) return;
- _errorMessages.Enqueue(message);
- _previousErrorMessage = message;
+ Error(error.Message);
}
///
@@ -3816,5 +3812,10 @@ private DateTime GetTimeInExchangeTimeZone(Symbol symbol)
var exchange = MarketHoursDatabase.GetExchangeHours(symbol.ID.Market, symbol, symbol.SecurityType);
return UtcTime.ConvertFromUtc(exchange.TimeZone);
}
+
+ private string FormatLog(string message)
+ {
+ return $"{Time.ToStringInvariant(DateFormat.UI)} {message}";
+ }
}
}
diff --git a/Algorithm/QuantConnect.Algorithm.csproj b/Algorithm/QuantConnect.Algorithm.csproj
index 030e18be98c2..2408b10fbce1 100644
--- a/Algorithm/QuantConnect.Algorithm.csproj
+++ b/Algorithm/QuantConnect.Algorithm.csproj
@@ -4,7 +4,7 @@
AnyCPU
QuantConnect.Algorithm
QuantConnect.Algorithm
- net9.0
+ net10.0
..\
false
AllEnabledByDefault
@@ -29,7 +29,7 @@
LICENSE
-
+
diff --git a/Algorithm/Risk/CompositeRiskManagementModel.cs b/Algorithm/Risk/CompositeRiskManagementModel.cs
index ae60e5836219..3f57989116d7 100644
--- a/Algorithm/Risk/CompositeRiskManagementModel.cs
+++ b/Algorithm/Risk/CompositeRiskManagementModel.cs
@@ -49,7 +49,7 @@ public CompositeRiskManagementModel(params IRiskManagementModel[] riskManagement
/// Initializes a new instance of the class
///
/// The individual risk management models defining this composite model
- public CompositeRiskManagementModel(IEnumerableriskManagementModels)
+ public CompositeRiskManagementModel(IEnumerable riskManagementModels)
{
foreach (var riskManagementModel in riskManagementModels)
{
@@ -129,11 +129,10 @@ public void AddRiskManagement(IRiskManagementModel riskManagementModel)
/// The risk management model to add
public void AddRiskManagement(PyObject pyRiskManagementModel)
{
- IRiskManagementModel riskManagementModel;
- if (!pyRiskManagementModel.TryConvert(out riskManagementModel))
- {
- riskManagementModel = new RiskManagementModelPythonWrapper(pyRiskManagementModel);
- }
+ var riskManagementModel = PythonUtil.CreateInstanceOrWrapper(
+ pyRiskManagementModel,
+ py => new RiskManagementModelPythonWrapper(py)
+ );
_riskManagementModels.Add(riskManagementModel);
}
}
diff --git a/Algorithm/Selection/CustomUniverseSelectionModel.cs b/Algorithm/Selection/CustomUniverseSelectionModel.cs
index 0b0dd71b29e0..eafc69ecc6b3 100644
--- a/Algorithm/Selection/CustomUniverseSelectionModel.cs
+++ b/Algorithm/Selection/CustomUniverseSelectionModel.cs
@@ -30,7 +30,6 @@ namespace QuantConnect.Algorithm.Framework.Selection
public class CustomUniverseSelectionModel : UniverseSelectionModel
{
private static readonly MarketHoursDatabase MarketHours = MarketHoursDatabase.FromDataFolder();
-
private readonly Symbol _symbol;
private readonly Func> _selector;
private readonly UniverseSettings _universeSettings;
@@ -105,7 +104,7 @@ public CustomUniverseSelectionModel(SecurityType securityType, string name, stri
public override IEnumerable CreateUniverses(QCAlgorithm algorithm)
{
var universeSettings = _universeSettings ?? algorithm.UniverseSettings;
- var entry = MarketHours.GetEntry(_symbol.ID.Market, (string) null, _symbol.SecurityType);
+ var entry = MarketHours.GetEntry(_symbol.ID.Market, (string)null, _symbol.SecurityType);
var config = new SubscriptionDataConfig(
universeSettings.Resolution == Resolution.Tick ? typeof(Tick) : typeof(TradeBar),
@@ -129,6 +128,12 @@ public override IEnumerable CreateUniverses(QCAlgorithm algorithm)
///
public virtual IEnumerable Select(QCAlgorithm algorithm, DateTime date)
{
+ // Check if this method was overridden in Python
+ if (TryInvokePythonOverride(nameof(Select), out IEnumerable result, algorithm, date))
+ {
+ return result;
+ }
+
if (_selector == null)
{
throw new ArgumentNullException(nameof(_selector));
diff --git a/Algorithm/Selection/UniverseSelectionModel.cs b/Algorithm/Selection/UniverseSelectionModel.cs
index e74d88940f55..68f070fcca9f 100644
--- a/Algorithm/Selection/UniverseSelectionModel.cs
+++ b/Algorithm/Selection/UniverseSelectionModel.cs
@@ -17,14 +17,23 @@
using System.Collections.Generic;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Interfaces;
+using QuantConnect.Python;
namespace QuantConnect.Algorithm.Framework.Selection
{
///
/// Provides a base class for universe selection models.
///
- public class UniverseSelectionModel : IUniverseSelectionModel
+ public class UniverseSelectionModel : BasePythonWrapper, IUniverseSelectionModel
{
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public UniverseSelectionModel()
+ {
+ }
+
///
/// Gets the next time the framework should invoke the `CreateUniverses` method to refresh the set of universes.
///
@@ -40,7 +49,7 @@ public virtual DateTime GetNextRefreshTimeUtc()
/// The universes to be used by the algorithm
public virtual IEnumerable CreateUniverses(QCAlgorithm algorithm)
{
- throw new System.NotImplementedException("Types deriving from 'UniverseSelectionModel' must implement the 'IEnumerable CreateUniverses(QCAlgorithm) method.");
+ throw new NotImplementedException("Types deriving from 'UniverseSelectionModel' must implement the 'IEnumerable CreateUniverses(QCAlgorithm) method.");
}
}
}
\ No newline at end of file
diff --git a/Algorithm/Selection/UniverseSelectionModelPythonWrapper.cs b/Algorithm/Selection/UniverseSelectionModelPythonWrapper.cs
index cbbcd4e3b1a5..8f2c88e14804 100644
--- a/Algorithm/Selection/UniverseSelectionModelPythonWrapper.cs
+++ b/Algorithm/Selection/UniverseSelectionModelPythonWrapper.cs
@@ -27,7 +27,6 @@ namespace QuantConnect.Algorithm.Framework.Selection
///
public class UniverseSelectionModelPythonWrapper : UniverseSelectionModel
{
- private readonly BasePythonWrapper _model;
private readonly bool _modelHasGetNextRefreshTime;
///
@@ -40,7 +39,7 @@ public override DateTime GetNextRefreshTimeUtc()
return DateTime.MaxValue;
}
- return _model.InvokeMethod(nameof(GetNextRefreshTimeUtc));
+ return InvokeMethod(nameof(GetNextRefreshTimeUtc));
}
///
@@ -49,18 +48,24 @@ public override DateTime GetNextRefreshTimeUtc()
/// Model defining universes for the algorithm
public UniverseSelectionModelPythonWrapper(PyObject model)
{
- _model = new BasePythonWrapper(model, false);
+ SetPythonInstance(model, false);
using (Py.GIL())
{
- _modelHasGetNextRefreshTime = _model.HasAttr(nameof(IUniverseSelectionModel.GetNextRefreshTimeUtc));
+ _modelHasGetNextRefreshTime = HasAttr(nameof(IUniverseSelectionModel.GetNextRefreshTimeUtc));
foreach (var attributeName in new[] { "CreateUniverses" })
{
- if (!_model.HasAttr(attributeName))
+ if (!HasAttr(attributeName))
{
throw new NotImplementedException($"UniverseSelectionModel.{attributeName} must be implemented. Please implement this missing method on {model.GetPythonType()}");
}
}
+
+ var methodName = nameof(SetPythonInstance);
+ if (HasAttr(methodName))
+ {
+ InvokeMethod(methodName, model);
+ }
}
}
@@ -71,7 +76,7 @@ public UniverseSelectionModelPythonWrapper(PyObject model)
/// The universes to be used by the algorithm
public override IEnumerable CreateUniverses(QCAlgorithm algorithm)
{
- return _model.InvokeMethodAndEnumerate(nameof(CreateUniverses), algorithm);
+ return InvokeMethodAndEnumerate(nameof(CreateUniverses), algorithm);
}
}
}
diff --git a/AlgorithmFactory/Python/Wrappers/AlgorithmPythonWrapper.cs b/AlgorithmFactory/Python/Wrappers/AlgorithmPythonWrapper.cs
index 4f9eb40171b0..7b9ff0cd4916 100644
--- a/AlgorithmFactory/Python/Wrappers/AlgorithmPythonWrapper.cs
+++ b/AlgorithmFactory/Python/Wrappers/AlgorithmPythonWrapper.cs
@@ -40,6 +40,7 @@
using QuantConnect.Commands;
using QuantConnect.Algorithm.Framework.Portfolio.SignalExports;
using QuantConnect.Algorithm.Framework.Execution;
+using Common.Util;
namespace QuantConnect.AlgorithmFactory.Python.Wrappers
{
@@ -181,7 +182,7 @@ public AlgorithmPythonWrapper(string moduleName)
catch (Exception e)
{
// perform exception interpretation for error in module import
- var interpreter = StackExceptionInterpreter.CreateFromAssemblies(AppDomain.CurrentDomain.GetAssemblies());
+ var interpreter = StackExceptionInterpreter.CreateFromAssemblies();
e = interpreter.Interpret(e, interpreter);
throw new Exception($"AlgorithmPythonWrapper(): {interpreter.GetExceptionMessageHeader(e)}");
@@ -681,7 +682,7 @@ public void OnEndOfTimeStep()
///
/// Gets a read-only dictionary with all current parameters
///
- public IReadOnlyDictionary GetParameters() => _baseAlgorithm.GetParameters();
+ public ReadOnlyExtendedDictionary GetParameters() => _baseAlgorithm.GetParameters();
///
/// Gets the parameter with the specified name. If a parameter with the specified name does not exist,
@@ -1087,9 +1088,23 @@ public void OnWarmupFinished()
/// Get the last known price using the history provider.
/// Useful for seeding securities with the correct price
///
- /// object for which to retrieve historical data
+ /// Symbol for which to retrieve historical data
/// A single object with the last known price
- public BaseData GetLastKnownPrice(Security security) => _baseAlgorithm.GetLastKnownPrice(security);
+ public BaseData GetLastKnownPrice(Symbol symbol) => _baseAlgorithm.GetLastKnownPrice(symbol);
+
+ ///
+ /// Yields data to warmup a security for all it's subscribed data types
+ ///
+ /// Symbol for which to retrieve historical data
+ /// Securities historical data
+ public IEnumerable GetLastKnownPrices(Symbol symbol) => _baseAlgorithm.GetLastKnownPrices(symbol);
+
+ ///
+ /// Yields data to warm up multiple securities for all their subscribed data types
+ ///
+ /// The symbols we want to get seed data for
+ /// Securities historical data
+ public DataDictionary> GetLastKnownPrices(IEnumerable symbols) => _baseAlgorithm.GetLastKnownPrices(symbols);
///
/// Set the runtime error
diff --git a/AlgorithmFactory/QuantConnect.AlgorithmFactory.csproj b/AlgorithmFactory/QuantConnect.AlgorithmFactory.csproj
index c0d552c13880..ac91612d6dba 100644
--- a/AlgorithmFactory/QuantConnect.AlgorithmFactory.csproj
+++ b/AlgorithmFactory/QuantConnect.AlgorithmFactory.csproj
@@ -4,7 +4,7 @@
AnyCPU
QuantConnect.AlgorithmFactory
QuantConnect.AlgorithmFactory
- net9.0
+ net10.0
false
bin\$(Configuration)\
AllEnabledByDefault
@@ -28,7 +28,7 @@
LICENSE
-
+
diff --git a/Api/Api.cs b/Api/Api.cs
index 72fc0e3175e5..37fc246a1a3e 100644
--- a/Api/Api.cs
+++ b/Api/Api.cs
@@ -20,9 +20,6 @@
using System.Net;
using System.Net.Http;
using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using RestSharp;
-using RestSharp.Extensions;
using QuantConnect.Interfaces;
using QuantConnect.Logging;
using QuantConnect.Optimizer.Objectives;
@@ -85,7 +82,7 @@ public Api()
///
public virtual void Initialize(int userId, string token, string dataFolder)
{
- ApiConnection = new ApiConnection(userId, token);
+ ApiConnection = CreateApiConnection(userId, token);
_dataFolder = dataFolder?.Replace("\\", "/", StringComparison.InvariantCulture);
//Allow proper decoding of orders from the API.
@@ -111,34 +108,11 @@ public virtual void Initialize(int userId, string token, string dataFolder)
public ProjectResponse CreateProject(string name, Language language, string organizationId = null)
{
- var request = new RestRequest("projects/create", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
+ object payload = string.IsNullOrEmpty(organizationId)
+ ? new { name, language }
+ : new { name, language, organizationId };
+ TryJsonPost("projects/create", out ProjectResponse result, payload);
- // Only include organization Id if its not null or empty
- string jsonParams;
- if (string.IsNullOrEmpty(organizationId))
- {
- jsonParams = JsonConvert.SerializeObject(new
- {
- name,
- language
- });
- }
- else
- {
- jsonParams = JsonConvert.SerializeObject(new
- {
- name,
- language,
- organizationId
- });
- }
-
- request.AddParameter("application/json", jsonParams, ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out ProjectResponse result);
return result;
}
@@ -150,17 +124,7 @@ public ProjectResponse CreateProject(string name, Language language, string orga
public ProjectResponse ReadProject(int projectId)
{
- var request = new RestRequest("projects/read", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- projectId
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out ProjectResponse result);
+ TryJsonPost("projects/read", out ProjectResponse result, new { projectId });
return result;
}
@@ -171,12 +135,7 @@ public ProjectResponse ReadProject(int projectId)
public ProjectResponse ListProjects()
{
- var request = new RestRequest("projects/read", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- ApiConnection.TryRequest(request, out ProjectResponse result);
+ TryJsonPost("projects/read", out ProjectResponse result);
return result;
}
@@ -191,23 +150,10 @@ public ProjectResponse ListProjects()
public RestResponse AddProjectFile(int projectId, string name, string content)
{
- var request = new RestRequest("files/create", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- projectId,
- name,
- content
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out RestResponse result);
+ TryJsonPost("files/create", out RestResponse result, new { projectId, name, content });
return result;
}
-
///
/// Update the name of a file
///
@@ -218,19 +164,13 @@ public RestResponse AddProjectFile(int projectId, string name, string content)
public RestResponse UpdateProjectFileName(int projectId, string oldFileName, string newFileName)
{
- var request = new RestRequest("files/update", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
+ var payload = new
{
projectId,
name = oldFileName,
newName = newFileName
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out RestResponse result);
+ };
+ TryJsonPost("files/update", out RestResponse result, payload);
return result;
}
@@ -245,19 +185,13 @@ public RestResponse UpdateProjectFileName(int projectId, string oldFileName, str
public RestResponse UpdateProjectFileContent(int projectId, string fileName, string newFileContents)
{
- var request = new RestRequest("files/update", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
+ var payload = new
{
projectId,
name = fileName,
content = newFileContents
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out RestResponse result);
+ };
+ TryJsonPost("files/update", out RestResponse result, payload);
return result;
}
@@ -270,17 +204,7 @@ public RestResponse UpdateProjectFileContent(int projectId, string fileName, str
public ProjectFilesResponse ReadProjectFiles(int projectId)
{
- var request = new RestRequest("files/read", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- projectId
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out ProjectFilesResponse result);
+ TryJsonPost("files/read", out ProjectFilesResponse result, new { projectId });
return result;
}
@@ -291,17 +215,7 @@ public ProjectFilesResponse ReadProjectFiles(int projectId)
/// that includes the information about all nodes in the project
public ProjectNodesResponse ReadProjectNodes(int projectId)
{
- var request = new RestRequest("projects/nodes/read", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- projectId
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out ProjectNodesResponse result);
+ TryJsonPost("projects/nodes/read", out ProjectNodesResponse result, new { projectId });
return result;
}
@@ -314,18 +228,7 @@ public ProjectNodesResponse ReadProjectNodes(int projectId)
/// that includes the information about all nodes in the project
public ProjectNodesResponse UpdateProjectNodes(int projectId, string[] nodes)
{
- var request = new RestRequest("projects/nodes/update", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- projectId,
- nodes
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out ProjectNodesResponse result);
+ TryJsonPost("projects/nodes/update", out ProjectNodesResponse result, new { projectId, nodes });
return result;
}
@@ -338,18 +241,7 @@ public ProjectNodesResponse UpdateProjectNodes(int projectId, string[] nodes)
public ProjectFilesResponse ReadProjectFile(int projectId, string fileName)
{
- var request = new RestRequest("files/read", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- projectId,
- name = fileName
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out ProjectFilesResponse result);
+ TryJsonPost("files/read", out ProjectFilesResponse result, new { projectId, name = fileName });
return result;
}
@@ -358,12 +250,7 @@ public ProjectFilesResponse ReadProjectFile(int projectId, string fileName)
///
public VersionsResponse ReadLeanVersions()
{
- var request = new RestRequest("lean/versions/read", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- ApiConnection.TryRequest(request, out VersionsResponse result);
+ TryPost("lean/versions/read", out VersionsResponse result);
return result;
}
@@ -376,18 +263,7 @@ public VersionsResponse ReadLeanVersions()
public RestResponse DeleteProjectFile(int projectId, string name)
{
- var request = new RestRequest("files/delete", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- projectId,
- name,
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out RestResponse result);
+ TryJsonPost("files/delete", out RestResponse result, new { projectId, name });
return result;
}
@@ -399,17 +275,7 @@ public RestResponse DeleteProjectFile(int projectId, string name)
public RestResponse DeleteProject(int projectId)
{
- var request = new RestRequest("projects/delete", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- projectId
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out RestResponse result);
+ TryJsonPost("projects/delete", out RestResponse result, new { projectId });
return result;
}
@@ -421,17 +287,7 @@ public RestResponse DeleteProject(int projectId)
public Compile CreateCompile(int projectId)
{
- var request = new RestRequest("compile/create", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- projectId
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out Compile result);
+ TryJsonPost("compile/create", out Compile result, new { projectId });
return result;
}
@@ -444,18 +300,7 @@ public Compile CreateCompile(int projectId)
public Compile ReadCompile(int projectId, string compileId)
{
- var request = new RestRequest("compile/read", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- projectId,
- compileId
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out Compile result);
+ TryJsonPost("compile/read", out Compile result, new { projectId, compileId });
return result;
}
@@ -480,19 +325,14 @@ public virtual RestResponse SendNotification(Notification notification, int proj
public Backtest CreateBacktest(int projectId, string compileId, string backtestName)
{
- var request = new RestRequest("backtests/create", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- projectId,
- compileId,
- backtestName
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out BacktestResponseWrapper result);
+ TryJsonPost("backtests/create",
+ out BacktestResponseWrapper result,
+ new
+ {
+ projectId,
+ compileId,
+ backtestName
+ });
// Use API Response values for Backtest Values
result.Backtest.Success = result.Success;
@@ -512,18 +352,7 @@ public Backtest CreateBacktest(int projectId, string compileId, string backtestN
public Backtest ReadBacktest(int projectId, string backtestId, bool getCharts = true)
{
- var request = new RestRequest("backtests/read", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- projectId,
- backtestId
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out BacktestResponseWrapper result);
+ TryJsonPost("backtests/read", out BacktestResponseWrapper result, new { projectId, backtestId });
if (result == null)
{
@@ -550,21 +379,14 @@ public Backtest ReadBacktest(int projectId, string backtestId, bool getCharts =
continue;
}
- var chartRequest = new RestRequest("backtests/chart/read", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- chartRequest.AddParameter("application/json", JsonConvert.SerializeObject(new
+ var payload = new
{
projectId,
backtestId,
name = chart.Key,
count = 100
- }), ParameterType.RequestBody);
-
- // Add this chart to our updated collection
- if (ApiConnection.TryRequest(chartRequest, out ReadChartResponse chartResponse) && chartResponse.Success)
+ };
+ if (TryJsonPost("backtests/chart/read", out ReadChartResponse chartResponse, payload) && chartResponse.Success)
{
updatedCharts.Add(chart.Key, chartResponse.Chart);
}
@@ -597,18 +419,13 @@ public Backtest ReadBacktest(int projectId, string backtestId, bool getCharts =
public List ReadBacktestOrders(int projectId, string backtestId, int start = 0, int end = 100)
{
- var request = new RestRequest("backtests/orders/read", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
+ using var request = ApiUtils.CreateJsonPostRequest("backtests/orders/read", new
{
start,
end,
projectId,
backtestId
- }), ParameterType.RequestBody);
+ });
return MakeRequestOrThrow(request, nameof(ReadBacktestOrders)).Orders;
}
@@ -625,12 +442,9 @@ public List ReadBacktestOrders(int projectId, string backtestI
/// The chart
public ReadChartResponse ReadBacktestChart(int projectId, string name, int start, int end, uint count, string backtestId)
{
- var request = new RestRequest("backtests/chart/read", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
+ const string resource = "backtests/chart/read";
+ // Serialize just once
+ var payloadStr = JsonConvert.SerializeObject(new
{
projectId,
name,
@@ -638,16 +452,17 @@ public ReadChartResponse ReadBacktestChart(int projectId, string name, int start
end,
count,
backtestId,
- }), ParameterType.RequestBody);
-
- ReadChartResponse result;
- ApiConnection.TryRequest(request, out result);
+ });
+ TryJsonPost(resource, out ReadChartResponse result, payloadStr);
- var finish = DateTime.UtcNow.AddMinutes(1);
- while (DateTime.UtcNow < finish && result.Chart == null)
+ if (result.Chart == null)
{
- Thread.Sleep(5000);
- ApiConnection.TryRequest(request, out result);
+ var finish = DateTime.UtcNow.AddMinutes(1);
+ while (DateTime.UtcNow < finish && result.Chart == null)
+ {
+ Thread.Sleep(5000);
+ TryJsonPost(resource, out result, payloadStr);
+ }
}
return result;
@@ -664,23 +479,10 @@ public ReadChartResponse ReadBacktestChart(int projectId, string name, int start
public RestResponse UpdateBacktest(int projectId, string backtestId, string name = null, string note = "")
{
- var request = new RestRequest("backtests/update", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- string payload;
- if (string.IsNullOrEmpty(name))
- {
- payload = JsonConvert.SerializeObject(new { projectId, backtestId, note });
- }
- else
- {
- payload = JsonConvert.SerializeObject(new { projectId, backtestId, note, name });
- }
- request.AddParameter("application/json", payload, ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out RestResponse result);
+ object payload = string.IsNullOrEmpty(name)
+ ? new { projectId, backtestId, note }
+ : new { projectId, backtestId, note, name };
+ TryJsonPost("backtests/update", out RestResponse result, payload);
return result;
}
@@ -693,20 +495,7 @@ public RestResponse UpdateBacktest(int projectId, string backtestId, string name
public BacktestSummaryList ListBacktests(int projectId, bool includeStatistics = true)
{
- var request = new RestRequest("backtests/list", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- var obj = new Dictionary()
- {
- { "projectId", projectId },
- { "includeStatistics", includeStatistics }
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(obj), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out BacktestSummaryList result);
+ TryJsonPost("backtests/list", out BacktestSummaryList result, new { projectId, includeStatistics });
return result;
}
@@ -719,18 +508,7 @@ public BacktestSummaryList ListBacktests(int projectId, bool includeStatistics =
public RestResponse DeleteBacktest(int projectId, string backtestId)
{
- var request = new RestRequest("backtests/delete", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- projectId,
- backtestId
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out RestResponse result);
+ TryJsonPost("backtests/delete", out RestResponse result, new { projectId, backtestId });
return result;
}
@@ -743,19 +521,7 @@ public RestResponse DeleteBacktest(int projectId, string backtestId)
///
public RestResponse UpdateBacktestTags(int projectId, string backtestId, IReadOnlyCollection tags)
{
- var request = new RestRequest("backtests/tags/update", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- projectId,
- backtestId,
- tags
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out RestResponse result);
+ TryJsonPost("backtests/tags/update", out RestResponse result, new { projectId, backtestId, tags });
return result;
}
@@ -770,11 +536,7 @@ public RestResponse UpdateBacktestTags(int projectId, string backtestId, IReadOn
///
public InsightResponse ReadBacktestInsights(int projectId, string backtestId, int start = 0, int end = 0)
{
- var request = new RestRequest("backtests/insights/read", Method.POST)
- {
- RequestFormat = DataFormat.Json,
- };
-
+ //var reque
var diff = end - start;
if (diff > 100)
{
@@ -785,17 +547,7 @@ public InsightResponse ReadBacktestInsights(int projectId, string backtestId, in
end = start + 100;
}
- JObject obj = new()
- {
- { "projectId", projectId },
- { "backtestId", backtestId },
- { "start", start },
- { "end", end },
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(obj), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out InsightResponse result);
+ TryJsonPost("backtests/insights/read", out InsightResponse result, new { projectId, backtestId, start, end });
return result;
}
@@ -827,23 +579,14 @@ public CreateLiveAlgorithmResponse CreateLiveAlgorithm(int projectId,
string versionId = "-1",
Dictionary dataProviders = null)
{
- var request = new RestRequest("live/create", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(
- new LiveAlgorithmApiSettingsWrapper
- (projectId,
+ var payload = new LiveAlgorithmApiSettingsWrapper(
+ projectId,
compileId,
nodeId,
brokerageSettings,
versionId,
- dataProviders
- )
- ), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out CreateLiveAlgorithmResponse result);
+ dataProviders);
+ TryJsonPost("live/create", out CreateLiveAlgorithmResponse result, payload);
return result;
}
@@ -905,21 +648,10 @@ public LiveList ListLiveAlgorithms(AlgorithmStatus? status = null)
"The Api only supports Algorithm Statuses of Running, Stopped, RuntimeError and Liquidated");
}
- var request = new RestRequest("live/list", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- var obj = new JObject();
-
- if (status.HasValue)
- {
- obj["status"] = status.ToString();
- }
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(obj), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out LiveList result);
+ var payload = status.HasValue
+ ? new { status = status.ToString() }
+ : null;
+ TryJsonPost("live/list", out LiveList result, payload);
return result;
}
@@ -932,18 +664,7 @@ public LiveList ListLiveAlgorithms(AlgorithmStatus? status = null)
public LiveAlgorithmResults ReadLiveAlgorithm(int projectId, string deployId)
{
- var request = new RestRequest("live/read", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- projectId,
- deployId
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out LiveAlgorithmResults result);
+ TryJsonPost("live/read", out LiveAlgorithmResults result, new { projectId, deployId });
return result;
}
@@ -954,17 +675,7 @@ public LiveAlgorithmResults ReadLiveAlgorithm(int projectId, string deployId)
///
public PortfolioResponse ReadLivePortfolio(int projectId)
{
- var request = new RestRequest("live/portfolio/read", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- projectId
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out PortfolioResponse result);
+ TryJsonPost("live/portfolio/read", out PortfolioResponse result, new { projectId });
return result;
}
@@ -979,17 +690,12 @@ public PortfolioResponse ReadLivePortfolio(int projectId)
public List ReadLiveOrders(int projectId, int start = 0, int end = 100)
{
- var request = new RestRequest("live/orders/read", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
+ using var request = ApiUtils.CreateJsonPostRequest("live/orders/read", new
{
start,
end,
projectId
- }), ParameterType.RequestBody);
+ });
return MakeRequestOrThrow(request, nameof(ReadLiveOrders)).Orders;
}
@@ -1002,17 +708,7 @@ public List ReadLiveOrders(int projectId, int start = 0, int e
public RestResponse LiquidateLiveAlgorithm(int projectId)
{
- var request = new RestRequest("live/update/liquidate", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- projectId
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out RestResponse result);
+ TryJsonPost("live/update/liquidate", out RestResponse result, new { projectId });
return result;
}
@@ -1023,17 +719,7 @@ public RestResponse LiquidateLiveAlgorithm(int projectId)
///
public RestResponse StopLiveAlgorithm(int projectId)
{
- var request = new RestRequest("live/update/stop", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- projectId
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out RestResponse result);
+ TryJsonPost("live/update/stop", out RestResponse result, new { projectId });
return result;
}
@@ -1045,18 +731,7 @@ public RestResponse StopLiveAlgorithm(int projectId)
///
public RestResponse CreateLiveCommand(int projectId, object command)
{
- var request = new RestRequest("live/commands/create", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- projectId,
- command
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out RestResponse result);
+ TryJsonPost("live/commands/create", out RestResponse result, new { projectId, command });
return result;
}
@@ -1069,19 +744,7 @@ public RestResponse CreateLiveCommand(int projectId, object command)
///
public RestResponse BroadcastLiveCommand(string organizationId, int? excludeProjectId, object command)
{
- var request = new RestRequest("live/commands/broadcast", Method.POST)
- {
- RequestFormat = DataFormat.Json,
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- organizationId,
- excludeProjectId,
- command
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out RestResponse result);
+ TryJsonPost("live/commands/broadcast", out RestResponse result, new { organizationId, excludeProjectId, command });
return result;
}
@@ -1101,21 +764,16 @@ public LiveLog ReadLiveLogs(int projectId, string algorithmId, int startLine, in
throw new ArgumentException($"The maximum number of log lines allowed is 250. But the number of log lines was {logLinesNumber}.");
}
- var request = new RestRequest("live/logs/read", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- format = "json",
- projectId,
- algorithmId,
- startLine,
- endLine,
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out LiveLog result);
+ TryJsonPost("live/logs/read",
+ out LiveLog result,
+ new
+ {
+ format = "json",
+ projectId,
+ algorithmId,
+ startLine,
+ endLine,
+ });
return result;
}
@@ -1130,29 +788,27 @@ public LiveLog ReadLiveLogs(int projectId, string algorithmId, int startLine, in
/// The chart
public ReadChartResponse ReadLiveChart(int projectId, string name, int start, int end, uint count)
{
- var request = new RestRequest("live/chart/read", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
+ const string resource = "live/chart/read";
+ var payloadStr = JsonConvert.SerializeObject(new
{
projectId,
name,
start,
end,
count
- }), ParameterType.RequestBody);
-
- ReadChartResponse result = default;
- ApiConnection.TryRequest(request, out result);
+ });
+ TryJsonPost(resource, out ReadChartResponse result, payloadStr);
- var finish = DateTime.UtcNow.AddMinutes(1);
- while (DateTime.UtcNow < finish && result.Chart == null)
+ if (result.Chart == null)
{
- Thread.Sleep(5000);
- ApiConnection.TryRequest(request, out result);
+ var finish = DateTime.UtcNow.AddMinutes(1);
+ while (DateTime.UtcNow < finish && result.Chart == null)
+ {
+ Thread.Sleep(5000);
+ TryJsonPost(resource, out result, payloadStr);
+ }
}
+
return result;
}
@@ -1166,11 +822,6 @@ public ReadChartResponse ReadLiveChart(int projectId, string name, int start, in
///
public InsightResponse ReadLiveInsights(int projectId, int start = 0, int end = 0)
{
- var request = new RestRequest("live/insights/read", Method.POST)
- {
- RequestFormat = DataFormat.Json,
- };
-
var diff = end - start;
if (diff > 100)
{
@@ -1181,16 +832,7 @@ public InsightResponse ReadLiveInsights(int projectId, int start = 0, int end =
end = start + 100;
}
- JObject obj = new JObject
- {
- { "projectId", projectId },
- { "start", start },
- { "end", end },
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(obj), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out InsightResponse result);
+ TryJsonPost("live/insights/read", out InsightResponse result, new { projectId, start, end });
return result;
}
@@ -1210,19 +852,14 @@ public DataLink ReadDataLink(string filePath, string organizationId)
// Prepare filePath for request
filePath = FormatPathForDataRequest(filePath);
- var request = new RestRequest("data/read", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- format = "link",
- filePath,
- organizationId
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out DataLink result);
+ TryJsonPost("data/read",
+ out DataLink result,
+ new
+ {
+ format = "link",
+ filePath,
+ organizationId
+ });
return result;
}
@@ -1248,17 +885,7 @@ public DataList ReadDataDirectory(string filePath)
$" three directories deep. FilePath: {filePath}");
}
- var request = new RestRequest("data/list", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- filePath
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out DataList result);
+ TryJsonPost("data/list", out DataList result, new { filePath });
return result;
}
@@ -1267,17 +894,7 @@ public DataList ReadDataDirectory(string filePath)
///
public DataPricesList ReadDataPrices(string organizationId)
{
- var request = new RestRequest("data/prices", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- organizationId
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out DataPricesList result);
+ TryJsonPost("data/prices", out DataPricesList result, new { organizationId });
return result;
}
@@ -1289,22 +906,13 @@ public DataPricesList ReadDataPrices(string organizationId)
///
public BacktestReport ReadBacktestReport(int projectId, string backtestId)
{
- var request = new RestRequest("backtests/read/report", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- backtestId,
- projectId
- }), ParameterType.RequestBody);
-
- BacktestReport report = new BacktestReport();
+ var payloadStr = JsonConvert.SerializeObject(new { backtestId, projectId });
+ var report = new BacktestReport();
var finish = DateTime.UtcNow.AddMinutes(1);
while (DateTime.UtcNow < finish && !report.Success)
{
Thread.Sleep(10000);
+ using var request = ApiUtils.CreateJsonPostRequest("backtests/read/report", payloadStr);
ApiConnection.TryRequest(request, out report);
}
return report;
@@ -1487,6 +1095,7 @@ public virtual void Dispose()
}
}
_clientPool.DisposeSafely();
+ ApiConnection?.DisposeSafely();
}
///
@@ -1507,17 +1116,7 @@ public static string CreateSecureHash(int timestamp, string token)
/// The target organization id, if null will return default organization
public Account ReadAccount(string organizationId = null)
{
- var request = new RestRequest("account/read", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- if (organizationId != null)
- {
- request.AddParameter("application/json", JsonConvert.SerializeObject(new { organizationId }), ParameterType.RequestBody);
- }
-
- ApiConnection.TryRequest(request, out Account account);
+ TryJsonPost("account/read", out Account account, organizationId != null ? new { organizationId } : null);
return account;
}
@@ -1528,17 +1127,7 @@ public Account ReadAccount(string organizationId = null)
///
public Organization ReadOrganization(string organizationId = null)
{
- var request = new RestRequest("organizations/read", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- if (organizationId != null)
- {
- request.AddParameter("application/json", JsonConvert.SerializeObject(new { organizationId }), ParameterType.RequestBody);
- }
-
- ApiConnection.TryRequest(request, out OrganizationResponse response);
+ TryJsonPost("organizations/read", out OrganizationResponse response, organizationId != null ? new { organizationId } : null);
return response.Organization;
}
@@ -1566,25 +1155,21 @@ public Estimate EstimateOptimization(
HashSet parameters,
IReadOnlyList constraints)
{
- var request = new RestRequest("optimizations/estimate", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- projectId,
- name,
- target,
- targetTo,
- targetValue,
- strategy,
- compileId,
- parameters,
- constraints
- }, SerializerSettings), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out EstimateResponseWrapper response);
+ TryJsonPost("optimizations/estimate",
+ out EstimateResponseWrapper response,
+ new
+ {
+ projectId,
+ name,
+ target,
+ targetTo,
+ targetValue,
+ strategy,
+ compileId,
+ parameters,
+ constraints
+ },
+ jsonSerializerSettings: SerializerSettings);
return response.Estimate;
}
@@ -1618,28 +1203,24 @@ public OptimizationSummary CreateOptimization(
string nodeType,
int parallelNodes)
{
- var request = new RestRequest("optimizations/create", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- projectId,
- name,
- target,
- targetTo,
- targetValue,
- strategy,
- compileId,
- parameters,
- constraints,
- estimatedCost,
- nodeType,
- parallelNodes
- }, SerializerSettings), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out OptimizationList result);
+ TryJsonPost("optimizations/create",
+ out OptimizationList result,
+ new
+ {
+ projectId,
+ name,
+ target,
+ targetTo,
+ targetValue,
+ strategy,
+ compileId,
+ parameters,
+ constraints,
+ estimatedCost,
+ nodeType,
+ parallelNodes
+ },
+ jsonSerializerSettings: SerializerSettings);
return result.Optimizations.FirstOrDefault();
}
@@ -1650,17 +1231,7 @@ public OptimizationSummary CreateOptimization(
/// A list of BaseOptimization objects,
public List ListOptimizations(int projectId)
{
- var request = new RestRequest("optimizations/list", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- projectId,
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out OptimizationList result);
+ TryJsonPost("optimizations/list", out OptimizationList result, new { projectId });
return result.Optimizations;
}
@@ -1671,17 +1242,7 @@ public List ListOptimizations(int projectId)
///
public Optimization ReadOptimization(string optimizationId)
{
- var request = new RestRequest("optimizations/read", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- optimizationId
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out OptimizationResponseWrapper response);
+ TryJsonPost("optimizations/read", out OptimizationResponseWrapper response, new { optimizationId });
return response.Optimization;
}
@@ -1692,17 +1253,7 @@ public Optimization ReadOptimization(string optimizationId)
///
public RestResponse AbortOptimization(string optimizationId)
{
- var request = new RestRequest("optimizations/abort", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- optimizationId
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out RestResponse result);
+ TryJsonPost("optimizations/abort", out RestResponse result, new { optimizationId });
return result;
}
@@ -1714,24 +1265,10 @@ public RestResponse AbortOptimization(string optimizationId)
///
public RestResponse UpdateOptimization(string optimizationId, string name = null)
{
- var request = new RestRequest("optimizations/update", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- var obj = new JObject
- {
- { "optimizationId", optimizationId }
- };
-
- if (name.HasValue())
- {
- obj.Add("name", name);
- }
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(obj), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out RestResponse result);
+ object paylaod = !string.IsNullOrEmpty(name)
+ ? new { optimizationId, name }
+ : new { optimizationId };
+ TryJsonPost("optimizations/update", out RestResponse result, paylaod);
return result;
}
@@ -1742,17 +1279,7 @@ public RestResponse UpdateOptimization(string optimizationId, string name = null
///
public RestResponse DeleteOptimization(string optimizationId)
{
- var request = new RestRequest("optimizations/delete", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- optimizationId
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out RestResponse result);
+ TryJsonPost("optimizations/delete", out RestResponse result, new { optimizationId });
return result;
}
@@ -1765,18 +1292,7 @@ public RestResponse DeleteOptimization(string optimizationId)
/// True if the object store files were retrieved correctly, false otherwise
public bool GetObjectStore(string organizationId, List keys, string destinationFolder = null)
{
- var request = new RestRequest("object/get", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(new
- {
- organizationId,
- keys
- }), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out GetObjectStoreResponse result);
+ TryJsonPost("object/get", out GetObjectStoreResponse result, new { organizationId, keys });
if (result == null || !result.Success)
{
@@ -1786,21 +1302,17 @@ public bool GetObjectStore(string organizationId, List keys, string dest
}
var jobId = result.JobId;
- var getUrlRequest = new RestRequest("object/get", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
- getUrlRequest.AddParameter("application/json", JsonConvert.SerializeObject(new
+ var getUrlPayloadStr = JsonConvert.SerializeObject(new
{
organizationId,
jobId
- }), ParameterType.RequestBody);
+ });
var frontier = DateTime.UtcNow + TimeSpan.FromMinutes(5);
while (string.IsNullOrEmpty(result?.Url) && (DateTime.UtcNow < frontier))
{
Thread.Sleep(3000);
- ApiConnection.TryRequest(getUrlRequest, out result);
+ TryJsonPost("object/get", out result, getUrlPayloadStr);
}
if (result == null || string.IsNullOrEmpty(result.Url))
@@ -1848,15 +1360,7 @@ public bool GetObjectStore(string organizationId, List keys, string dest
/// It does not work when the object store is a directory
public PropertiesObjectStoreResponse GetObjectStoreProperties(string organizationId, string key)
{
- var request = new RestRequest("object/properties", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- request.AddParameter("organizationId", organizationId);
- request.AddParameter("key", key);
-
- ApiConnection.TryRequest(request, out PropertiesObjectStoreResponse result);
+ TryJsonPost("object/properties", out PropertiesObjectStoreResponse result, new { organizationId, key });
if (result == null || !result.Success)
{
@@ -1874,16 +1378,18 @@ public PropertiesObjectStoreResponse GetObjectStoreProperties(string organizatio
///
public RestResponse SetObjectStore(string organizationId, string key, byte[] objectData)
{
- var request = new RestRequest("object/set", Method.POST)
+ // HttpRequestMessage will dispose of the content and MultipartFormDataContent will dispose of its children
+#pragma warning disable CA2000 // Dispose objects before losing scope
+ using var request = new HttpRequestMessage(HttpMethod.Post, "object/set")
{
- RequestFormat = DataFormat.Json
+ Content = new MultipartFormDataContent()
+ {
+ { new StringContent(organizationId), "organizationId" },
+ { new StringContent(key), "key" },
+ { new ByteArrayContent(objectData), "objectData", "objectData" }
+ }
};
-
- request.AddParameter("organizationId", organizationId);
- request.AddParameter("key", key);
- request.AddFileBytes("objectData", objectData, "objectData");
- request.AlwaysMultipartFormData = true;
-
+#pragma warning restore CA2000 // Dispose objects before losing scope
ApiConnection.TryRequest(request, out RestResponse result);
return result;
}
@@ -1896,20 +1402,7 @@ public RestResponse SetObjectStore(string organizationId, string key, byte[] obj
///
public RestResponse DeleteObjectStore(string organizationId, string key)
{
- var request = new RestRequest("object/delete", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- var obj = new Dictionary
- {
- { "organizationId", organizationId },
- { "key", key }
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(obj), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out RestResponse result);
+ TryJsonPost("object/delete", out RestResponse result, new { organizationId, key });
return result;
}
@@ -1921,20 +1414,7 @@ public RestResponse DeleteObjectStore(string organizationId, string key)
///
public ListObjectStoreResponse ListObjectStore(string organizationId, string path)
{
- var request = new RestRequest("object/list", Method.POST)
- {
- RequestFormat = DataFormat.Json
- };
-
- var obj = new Dictionary
- {
- { "organizationId", organizationId },
- { "path", path }
- };
-
- request.AddParameter("application/json", JsonConvert.SerializeObject(obj), ParameterType.RequestBody);
-
- ApiConnection.TryRequest(request, out ListObjectStoreResponse result);
+ TryJsonPost("object/list", out ListObjectStoreResponse result, new { organizationId, path });
return result;
}
@@ -1968,10 +1448,42 @@ public static string FormatPathForDataRequest(string filePath, string dataFolder
return filePath;
}
+ ///
+ /// Makes a simple POST request to the specified endpoint with the given payload
+ ///
+ protected bool TryPost(string endpoint, out T result, IEnumerable> payload = null,
+ ApiConnection apiConnection = null, TimeSpan? timeout = null)
+ where T : RestResponse
+ {
+ using var request = ApiUtils.CreatePostRequest(endpoint, payload);
+
+ return (apiConnection ?? ApiConnection).TryRequest(request, out result, timeout);
+ }
+
+ ///
+ /// Makes a simple POST request to the specified endpoint with the given payload
+ ///
+ protected bool TryJsonPost(string endpoint, out T result, object payload = null,
+ ApiConnection apiConnection = null, JsonSerializerSettings jsonSerializerSettings = null, TimeSpan? timeout = null)
+ where T : RestResponse
+ {
+ using var request = ApiUtils.CreateJsonPostRequest(endpoint, payload, jsonSerializerSettings);
+
+ return (apiConnection ?? ApiConnection).TryRequest(request, out result, timeout);
+ }
+
+ ///
+ /// Create the api connection instance to use
+ ///
+ protected virtual ApiConnection CreateApiConnection(int userId, string token)
+ {
+ return new ApiConnection(userId, token);
+ }
+
///
/// Helper method that will execute the given api request and throw an exception if it fails
///
- private T MakeRequestOrThrow(RestRequest request, string callerName)
+ private T MakeRequestOrThrow(HttpRequestMessage request, string callerName)
where T : RestResponse
{
if (!ApiConnection.TryRequest(request, out T result))
diff --git a/Api/ApiConnection.cs b/Api/ApiConnection.cs
index b3e9afa5ab91..3152751d312a 100644
--- a/Api/ApiConnection.cs
+++ b/Api/ApiConnection.cs
@@ -15,24 +15,32 @@
using System;
using RestSharp;
-using Newtonsoft.Json;
-using QuantConnect.Orders;
using QuantConnect.Logging;
using System.Threading.Tasks;
-using RestSharp.Authenticators;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Text;
+using System.Collections.Generic;
+using QuantConnect.Util;
+using System.IO;
+using System.Threading;
namespace QuantConnect.Api
{
///
/// API Connection and Hash Manager
///
- public class ApiConnection
+ public class ApiConnection : IDisposable
{
- private readonly static JsonSerializerSettings _jsonSettings = new() { Converters = { new LiveAlgorithmResultsJsonConverter(), new OrderJsonConverter() } };
+ ///
+ /// Authorized client to use for requests.
+ ///
+ private HttpClient _httpClient;
///
/// Authorized client to use for requests.
///
+ [Obsolete("RestSharp is deprecated and will be removed in a future release. Please use the SetClient method or the request methods that take an HttpRequestMessage")]
public RestClient Client { get; set; }
// Authorization Credentials
@@ -47,10 +55,23 @@ public class ApiConnection
/// User Id number from QuantConnect.com account. Found at www.quantconnect.com/account
/// Access token for the QuantConnect account. Found at www.quantconnect.com/account
public ApiConnection(int userId, string token)
+ : this(userId, token, null)
+ {
+ }
+
+ ///
+ /// Create a new Api Connection Class.
+ ///
+ /// User Id number from QuantConnect.com account. Found at www.quantconnect.com/account
+ /// Access token for the QuantConnect account. Found at www.quantconnect.com/account
+ /// The client's base address
+ /// Default headers for the client
+ /// The client timeout in seconds
+ public ApiConnection(int userId, string token, string baseUrl = null, Dictionary defaultHeaders = null, int timeout = 0)
{
_token = token;
_userId = userId.ToStringInvariant();
- Client = new RestClient(Globals.Api);
+ SetClient(!string.IsNullOrEmpty(baseUrl) ? baseUrl : Globals.Api, defaultHeaders, timeout);
}
///
@@ -60,16 +81,55 @@ public bool Connected
{
get
{
- var request = new RestRequest("authenticate", Method.GET);
- AuthenticationResponse response;
- if (TryRequest(request, out response))
+ using var request = new HttpRequestMessage(HttpMethod.Get, "authenticate");
+ return TryRequest(request, out AuthenticationResponse response) && response.Success;
+ }
+ }
+
+ ///
+ /// Overrides the current client
+ ///
+ /// The client's base address
+ /// Default headers for the client
+ /// The client timeout in seconds
+ public void SetClient(string baseUrl, Dictionary defaultHeaders = null, int timeout = 0)
+ {
+ if (_httpClient != null)
+ {
+ _httpClient.DisposeSafely();
+ }
+
+ _httpClient = new HttpClient() { BaseAddress = new Uri($"{baseUrl.TrimEnd('/')}/") };
+ Client = new RestClient(baseUrl);
+
+ if (defaultHeaders != null)
+ {
+ foreach (var header in defaultHeaders)
{
- return response.Success;
+ _httpClient.DefaultRequestHeaders.Add(header.Key, header.Value);
}
- return false;
+ Client.AddDefaultHeaders(defaultHeaders);
+ }
+
+ if (timeout > 0)
+ {
+ _httpClient.Timeout = TimeSpan.FromSeconds(timeout);
+ Client.Timeout = timeout * 1000;
+ }
+ else
+ {
+ _httpClient.Timeout = Timeout.InfiniteTimeSpan;
}
}
+ ///
+ /// Disposes of the HTTP client
+ ///
+ public void Dispose()
+ {
+ _httpClient.Dispose();
+ }
+
///
/// Place a secure request and get back an object of type T.
///
@@ -77,6 +137,7 @@ public bool Connected
///
/// Result object from the
/// T typed object response
+ [Obsolete("RestSharp is deprecated and will be removed in a future release. Please use the TryRequest(HttpRequestMessage)")]
public bool TryRequest(RestRequest request, out T result)
where T : RestResponse
{
@@ -90,7 +151,24 @@ public bool TryRequest(RestRequest request, out T result)
///
///
///
+ /// Result object from the
+ /// Timeout for the request
/// T typed object response
+ public bool TryRequest(HttpRequestMessage request, out T result, TimeSpan? timeout = null)
+ where T : RestResponse
+ {
+ var resultTuple = TryRequestAsync(request, timeout).SynchronouslyAwaitTaskResult();
+ result = resultTuple.Item2;
+ return resultTuple.Item1;
+ }
+
+ ///
+ /// Place a secure request and get back an object of type T.
+ ///
+ ///
+ ///
+ /// T typed object response
+ [Obsolete("RestSharp is deprecated and will be removed in a future release. Please use the TryRequestAsync(HttpRequestMessage)")]
public async Task> TryRequestAsync(RestRequest request)
where T : RestResponse
{
@@ -116,7 +194,7 @@ public async Task> TryRequestAsync(RestRequest request)
}
responseContent = restsharpResponse.Content;
- result = JsonConvert.DeserializeObject(responseContent, _jsonSettings);
+ result = responseContent.DeserializeJson();
if (result == null || !result.Success)
{
@@ -133,10 +211,106 @@ public async Task> TryRequestAsync(RestRequest request)
return new Tuple(true, result);
}
+ ///
+ /// Place a secure request and get back an object of type T.
+ ///
+ ///
+ ///
+ /// Timeout for the request
+ /// T typed object response
+ public async Task> TryRequestAsync(HttpRequestMessage request, TimeSpan? timeout = null)
+ where T : RestResponse
+ {
+ HttpResponseMessage response = null;
+ Stream responseContentStream = null;
+ T result = null;
+
+ // Default to 100 seconds (since we disabled the default client timeout)
+ timeout ??= TimeSpan.FromSeconds(100);
+
+ try
+ {
+ if (request.RequestUri.OriginalString.StartsWith('/'))
+ {
+ request.RequestUri = new Uri(request.RequestUri.ToString().TrimStart('/'), UriKind.Relative);
+ }
+
+ SetAuthenticator(request);
+
+ // Execute the authenticated REST API Call
+ using var cancellationTokenSource = new CancellationTokenSource(timeout.Value);
+ response = await _httpClient.SendAsync(request, cancellationTokenSource.Token).ConfigureAwait(false);
+ responseContentStream = await response.Content.ReadAsStreamAsync(cancellationTokenSource.Token).ConfigureAwait(false);
+
+ result = responseContentStream.DeserializeJson(leaveOpen: true);
+
+ if (!response.IsSuccessStatusCode)
+ {
+ Log.Error($"ApiConnect.TryRequest({request.RequestUri}): HTTP Error: {(int)response.StatusCode} {response.ReasonPhrase}. " +
+ $"Content: {GetRawResponseContent(responseContentStream)}");
+ }
+ if (result == null || !result.Success)
+ {
+ if (Log.DebuggingEnabled)
+ {
+ Log.Debug($"ApiConnection.TryRequest({request.RequestUri}): Raw response: '{GetRawResponseContent(responseContentStream)}'");
+ }
+ return new Tuple(false, result);
+ }
+ }
+ catch (Exception err)
+ {
+ Log.Error($"ApiConnection.TryRequest({request.RequestUri}): Error: {err.Message}, Response content: {GetRawResponseContent(responseContentStream)}");
+ return new Tuple(false, null);
+ }
+ finally
+ {
+ response?.DisposeSafely();
+ responseContentStream?.DisposeSafely();
+ }
+
+ return new Tuple(true, result);
+ }
+
+ private static string GetRawResponseContent(Stream stream)
+ {
+ if (stream == null)
+ {
+ return string.Empty;
+ }
+
+ try
+ {
+ stream.Position = 0;
+ using var reader = new StreamReader(stream, leaveOpen: true);
+ return reader.ReadToEnd();
+ }
+ catch (Exception)
+ {
+ return string.Empty;
+ }
+ }
+
private void SetAuthenticator(RestRequest request)
{
- var newTimeStamp = (int)Time.TimeStamp();
+ var base64EncodedAuthenticationString = GetAuthenticatorHeader(out var timeStamp);
+ request.AddOrUpdateHeader("Authorization", $"Basic {base64EncodedAuthenticationString}");
+ request.AddOrUpdateHeader("Timestamp", timeStamp);
+ }
+
+ private void SetAuthenticator(HttpRequestMessage request)
+ {
+ request.Headers.Remove("Authorization");
+ request.Headers.Remove("Timestamp");
+
+ var base64EncodedAuthenticationString = GetAuthenticatorHeader(out var timeStamp);
+ _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", base64EncodedAuthenticationString);
+ request.Headers.Add("Timestamp", timeStamp);
+ }
+ private string GetAuthenticatorHeader(out string timeStamp)
+ {
+ var newTimeStamp = (int)Time.TimeStamp();
var currentAuth = _authenticator;
if (currentAuth == null || newTimeStamp - currentAuth.TimeStamp > 7000)
{
@@ -144,25 +318,25 @@ private void SetAuthenticator(RestRequest request)
// Add the UTC timestamp to the request header.
// Timestamps older than 7200 seconds will not work.
var hash = Api.CreateSecureHash(newTimeStamp, _token);
- var authenticator = new HttpBasicAuthenticator(_userId, hash);
- _authenticator = currentAuth = new LeanAuthenticator(authenticator, newTimeStamp);
-
- Client.Authenticator = currentAuth.Authenticator;
+ var authenticationString = $"{_userId}:{hash}";
+ var base64EncodedAuthenticationString = Convert.ToBase64String(Encoding.UTF8.GetBytes(authenticationString));
+ _authenticator = currentAuth = new LeanAuthenticator(newTimeStamp, base64EncodedAuthenticationString);
}
- request.AddHeader("Timestamp", currentAuth.TimeStampStr);
+ timeStamp = currentAuth.TimeStampStr;
+ return currentAuth.Base64EncodedAuthenticationString;
}
private class LeanAuthenticator
{
public int TimeStamp { get; }
public string TimeStampStr { get; }
- public HttpBasicAuthenticator Authenticator { get; }
- public LeanAuthenticator(HttpBasicAuthenticator authenticator, int timeStamp)
+ public string Base64EncodedAuthenticationString { get; }
+ public LeanAuthenticator(int timeStamp, string base64EncodedAuthenticationString)
{
TimeStamp = timeStamp;
- Authenticator = authenticator;
TimeStampStr = timeStamp.ToStringInvariant();
+ Base64EncodedAuthenticationString = base64EncodedAuthenticationString;
}
}
}
diff --git a/Api/ApiUtils.cs b/Api/ApiUtils.cs
new file mode 100644
index 000000000000..1fcebdcf4dee
--- /dev/null
+++ b/Api/ApiUtils.cs
@@ -0,0 +1,65 @@
+/*
+ * 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.Net.Http;
+using System.Collections.Generic;
+using Newtonsoft.Json;
+using System.Net.Http.Headers;
+using System.Net.Mime;
+
+namespace QuantConnect.Api
+{
+ ///
+ /// API utility methods
+ ///
+ public static class ApiUtils
+ {
+ ///
+ /// Creates a POST with the specified endpoint and payload as form url encoded content.
+ ///
+ /// The request endpoint
+ /// The request payload
+ /// The POST request
+ public static HttpRequestMessage CreatePostRequest(string endpoint, IEnumerable> payload = null)
+ {
+ var request = new HttpRequestMessage(HttpMethod.Post, endpoint);
+ if (payload != null)
+ {
+ request.Content = new FormUrlEncodedContent(payload);
+ }
+
+ return request;
+ }
+
+ ///
+ /// Creates a POST with the specified endpoint and payload as json body
+ ///
+ /// The request endpoint
+ /// The request payload
+ /// Settings for the json serializer
+ /// The POST request
+ public static HttpRequestMessage CreateJsonPostRequest(string endpoint, object payload = null, JsonSerializerSettings jsonSerializerSettings = null)
+ {
+ var request = new HttpRequestMessage(HttpMethod.Post, endpoint);
+ if (payload != null)
+ {
+ request.Content = new StringContent(payload as string ?? JsonConvert.SerializeObject(payload, jsonSerializerSettings),
+ new MediaTypeHeaderValue(MediaTypeNames.Application.Json));
+ }
+
+ return request;
+ }
+ }
+}
diff --git a/Api/QuantConnect.Api.csproj b/Api/QuantConnect.Api.csproj
index 20fb363b8669..4c06a2e5213e 100644
--- a/Api/QuantConnect.Api.csproj
+++ b/Api/QuantConnect.Api.csproj
@@ -4,7 +4,7 @@
AnyCPU
QuantConnect.Api
QuantConnect.Api
- net9.0
+ net10.0
..\
true
AllEnabledByDefault
diff --git a/Brokerages/Authentication/OAuthTokenHandler.cs b/Brokerages/Authentication/OAuthTokenHandler.cs
index d82ed48e175b..f3bac7279ddb 100644
--- a/Brokerages/Authentication/OAuthTokenHandler.cs
+++ b/Brokerages/Authentication/OAuthTokenHandler.cs
@@ -14,7 +14,6 @@
*/
using System;
-using RestSharp;
using QuantConnect.Api;
using System.Threading;
@@ -76,8 +75,7 @@ public override TokenCredentials GetAccessToken(CancellationToken cancellationTo
try
{
- var request = new RestRequest("live/auth0/refresh", Method.POST);
- request.AddJsonBody(_jsonBodyRequest);
+ using var request = ApiUtils.CreateJsonPostRequest("live/auth0/refresh", _jsonBodyRequest);
if (_apiClient.TryRequest(request, out var response))
{
diff --git a/Brokerages/Backtesting/BacktestingBrokerage.cs b/Brokerages/Backtesting/BacktestingBrokerage.cs
index 8e6c6064e840..8f6b2e1068d8 100644
--- a/Brokerages/Backtesting/BacktestingBrokerage.cs
+++ b/Brokerages/Backtesting/BacktestingBrokerage.cs
@@ -27,6 +27,7 @@
using QuantConnect.Securities;
using QuantConnect.Securities.Option;
using QuantConnect.Util;
+using System.Collections.Specialized;
namespace QuantConnect.Brokerages.Backtesting
{
@@ -553,10 +554,12 @@ public void ProcessDelistings(Delistings delistings)
var universe = ukvp.Value;
if (universe.ContainsMember(security.Symbol))
{
- var userUniverse = universe as UserDefinedUniverse;
- if (userUniverse != null)
+ if (universe is UserDefinedUniverse userUniverse)
{
- userUniverse.Remove(security.Symbol);
+ if (userUniverse.Remove(security.Symbol))
+ {
+ Algorithm.UniverseManager.Update(userUniverse.Symbol, userUniverse, NotifyCollectionChangedAction.Replace);
+ }
}
else
{
@@ -564,6 +567,7 @@ public void ProcessDelistings(Delistings delistings)
}
}
}
+ Algorithm.UniverseManager.ProcessChanges();
if (!Algorithm.IsWarmingUp)
{
diff --git a/Brokerages/BaseWebsocketsBrokerage.cs b/Brokerages/BaseWebsocketsBrokerage.cs
index 2385abaa1f42..12f932e7ed23 100644
--- a/Brokerages/BaseWebsocketsBrokerage.cs
+++ b/Brokerages/BaseWebsocketsBrokerage.cs
@@ -21,6 +21,7 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
+using System.Net.Http;
using System.Threading;
namespace QuantConnect.Brokerages
@@ -33,6 +34,9 @@ public abstract class BaseWebsocketsBrokerage : Brokerage
{
private const int ConnectionTimeout = 30000;
+ private IRestClient _restClient;
+ private HttpClient _httpClient;
+
///
/// True if the current brokerage is already initialized
///
@@ -46,7 +50,41 @@ public abstract class BaseWebsocketsBrokerage : Brokerage
///
/// The rest client instance
///
- protected IRestClient RestClient { get; set; }
+ [Obsolete("RestClient is deprecated. Use HttpClient property instead")]
+ protected IRestClient RestClient
+ {
+ get
+ {
+ if (_restClient == null)
+ {
+ throw new InvalidOperationException("RestClient not initialized");
+ }
+ return _restClient;
+ }
+ set
+ {
+ _restClient = value;
+ }
+ }
+
+ ///
+ /// The HTTP client instance
+ ///
+ protected HttpClient HttpClient
+ {
+ get
+ {
+ if (_httpClient == null)
+ {
+ throw new InvalidOperationException("HttpClient not initialized");
+ }
+ return _httpClient;
+ }
+ set
+ {
+ _httpClient = value;
+ }
+ }
///
/// standard json parsing settings
@@ -81,11 +119,36 @@ public abstract class BaseWebsocketsBrokerage : Brokerage
/// instance of rest client
/// api key
/// api secret
+ [Obsolete("This Initialize method is deprecated. Use the overload that takes an HttpClient instance instead.")]
protected void Initialize(string wssUrl, IWebSocket websocket, IRestClient restClient, string apiKey, string apiSecret)
+ {
+ if (TryInitialize(wssUrl, websocket, apiKey, apiSecret))
+ {
+ RestClient = restClient;
+ }
+ }
+
+ ///
+ /// Initialize the instance of this class
+ ///
+ /// The web socket base url
+ /// Instance of websockets client
+ /// Instance of HTTP client
+ /// Api key
+ /// Api secret
+ protected void Initialize(string wssUrl, IWebSocket websocket, HttpClient httpClient, string apiKey, string apiSecret)
+ {
+ if (TryInitialize(wssUrl, websocket, apiKey, apiSecret))
+ {
+ HttpClient = httpClient;
+ }
+ }
+
+ private bool TryInitialize(string wssUrl, IWebSocket websocket, string apiKey, string apiSecret)
{
if (IsInitialized)
{
- return;
+ return false;
}
IsInitialized = true;
JsonSettings = new JsonSerializerSettings { FloatParseHandling = FloatParseHandling.Decimal };
@@ -101,9 +164,10 @@ protected void Initialize(string wssUrl, IWebSocket websocket, IRestClient restC
Subscribe(GetSubscribed());
};
- RestClient = restClient;
ApiSecret = apiSecret;
ApiKey = apiKey;
+
+ return true;
}
///
diff --git a/Brokerages/Brokerage.cs b/Brokerages/Brokerage.cs
index 418e10fe74c5..6af0b2dc6e2a 100644
--- a/Brokerages/Brokerage.cs
+++ b/Brokerages/Brokerage.cs
@@ -27,6 +27,7 @@
using System.Collections.Generic;
using System.Collections.Concurrent;
using QuantConnect.Brokerages.CrossZero;
+using QuantConnect.Util;
namespace QuantConnect.Brokerages
{
@@ -509,6 +510,11 @@ public virtual bool PerformCashSync(IAlgorithm algorithm, DateTime currentTimeUt
{
if (!algorithm.Portfolio.CashBook.ContainsKey(balance.Currency))
{
+ if (!CashAmountUtil.ShouldAddCashBalance(balance, algorithm.AccountCurrency))
+ {
+ Log.Trace($"Brokerage.PerformCashSync(): Skipping {balance.Currency} cash because quantity is zero");
+ continue;
+ }
Log.Trace($"Brokerage.PerformCashSync(): Unexpected cash found {balance.Currency} {balance.Amount}", true);
algorithm.Portfolio.SetCash(balance.Currency, balance.Amount, 0);
}
@@ -756,7 +762,7 @@ protected bool TryGetOrRemoveCrossZeroOrder(string brokerageOrderId, OrderStatus
case OrderStatus.Invalid:
LeanOrderByZeroCrossBrokerageOrderId.TryRemove(brokerageOrderId, out var _);
break;
- };
+ }
return true;
}
// Return false if the brokerage order ID does not correspond to a cross-zero order
@@ -787,7 +793,7 @@ protected bool TryHandleRemainingCrossZeroOrder(Order leanOrder, OrderEvent orde
return false;
default:
return false;
- };
+ }
OnOrderEvent(orderEvent);
diff --git a/Brokerages/QuantConnect.Brokerages.csproj b/Brokerages/QuantConnect.Brokerages.csproj
index 96f6221d4106..e44042df0a51 100644
--- a/Brokerages/QuantConnect.Brokerages.csproj
+++ b/Brokerages/QuantConnect.Brokerages.csproj
@@ -4,7 +4,7 @@
AnyCPU
QuantConnect.Brokerages
QuantConnect.Brokerages
- net9.0
+ net10.0
AllEnabledByDefault
false
bin\$(Configuration)\
diff --git a/Common/Algorithm/Framework/Alphas/Analysis/InsightManager.cs b/Common/Algorithm/Framework/Alphas/Analysis/InsightManager.cs
index 6a7909e01ac2..2c6da8a21c5b 100644
--- a/Common/Algorithm/Framework/Alphas/Analysis/InsightManager.cs
+++ b/Common/Algorithm/Framework/Alphas/Analysis/InsightManager.cs
@@ -17,6 +17,7 @@
using Python.Runtime;
using QuantConnect.Interfaces;
using System.Collections.Generic;
+using QuantConnect.Util;
namespace QuantConnect.Algorithm.Framework.Alphas.Analysis
{
@@ -61,15 +62,10 @@ public void SetInsightScoreFunction(IInsightScoreFunction insightScoreFunction)
/// Model that scores insights
public void SetInsightScoreFunction(PyObject insightScoreFunction)
{
- IInsightScoreFunction model;
- if (insightScoreFunction.TryConvert(out model))
- {
- SetInsightScoreFunction(model);
- }
- else
- {
- _insightScoreFunction = new InsightScoreFunctionPythonWrapper(insightScoreFunction);
- }
+ _insightScoreFunction = PythonUtil.CreateInstanceOrWrapper(
+ insightScoreFunction,
+ py => new InsightScoreFunctionPythonWrapper(py)
+ );
}
///
diff --git a/Common/Algorithm/Framework/Portfolio/SignalExports/SignalExportManager.cs b/Common/Algorithm/Framework/Portfolio/SignalExports/SignalExportManager.cs
index 017d6f097977..65d74d9c96e3 100644
--- a/Common/Algorithm/Framework/Portfolio/SignalExports/SignalExportManager.cs
+++ b/Common/Algorithm/Framework/Portfolio/SignalExports/SignalExportManager.cs
@@ -84,10 +84,10 @@ public void AddSignalExportProvider(ISignalExportTarget signalExport)
/// Signal export provider
public void AddSignalExportProvider(PyObject signalExport)
{
- if (!signalExport.TryConvert(out var managedSignalExport))
- {
- managedSignalExport = new SignalExportTargetPythonWrapper(signalExport);
- }
+ var managedSignalExport = PythonUtil.CreateInstanceOrWrapper(
+ signalExport,
+ py => new SignalExportTargetPythonWrapper(py)
+ );
AddSignalExportProvider(managedSignalExport);
}
@@ -172,7 +172,7 @@ public bool SetTargetPortfolio(params PortfolioTarget[] portfolioTargets)
}
if (_signalExports.IsNullOrEmpty())
- {
+ {
return false;
}
diff --git a/Common/AlgorithmSettings.cs b/Common/AlgorithmSettings.cs
index e8eaec146a7e..ae79dfd43544 100644
--- a/Common/AlgorithmSettings.cs
+++ b/Common/AlgorithmSettings.cs
@@ -173,6 +173,11 @@ public Resolution? WarmUpResolution
///
public TimeSpan PerformanceSamplePeriod { get; set; }
+ ///
+ /// Determines whether to seed initial prices for all selected and manually added securities.
+ ///
+ public bool SeedInitialPrices { get; set; }
+
///
/// Initializes a new instance of the class
///
@@ -189,6 +194,7 @@ public AlgorithmSettings()
MinAbsolutePortfolioTargetPercentage = 0.0000000001m;
DatabasesRefreshPeriod = _defaultDatabasesRefreshPeriod;
IgnoreUnknownAssetHoldings = _defaultIgnoreUnknownAssetHoldings;
+ SeedInitialPrices = false;
}
}
}
diff --git a/Common/AlgorithmUtils.cs b/Common/AlgorithmUtils.cs
new file mode 100644
index 000000000000..df62c3b46b93
--- /dev/null
+++ b/Common/AlgorithmUtils.cs
@@ -0,0 +1,50 @@
+/*
+ * 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 QuantConnect.Interfaces;
+using QuantConnect.Securities;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace QuantConnect
+{
+ ///
+ /// Provides utility methods for or related to algorithms
+ ///
+ public static class AlgorithmUtils
+ {
+ ///
+ /// Seeds the provided securities with their last known prices from the algorithm
+ ///
+ /// The securities to seed
+ /// The algorithm instance
+ public static void SeedSecurities(IReadOnlyCollection securities, IAlgorithm algorithm)
+ {
+ var securitiesToSeed = securities.Where(x => x.Price == 0);
+ var data = algorithm.GetLastKnownPrices(securitiesToSeed.Select(x => x.Symbol));
+
+ foreach (var security in securitiesToSeed)
+ {
+ if (data.TryGetValue(security.Symbol, out var seedData))
+ {
+ foreach (var datum in seedData)
+ {
+ security.SetMarketPrice(datum);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/Common/Api/Nodes.cs b/Common/Api/Nodes.cs
index 1cc97e9e7046..f1a39da30b15 100644
--- a/Common/Api/Nodes.cs
+++ b/Common/Api/Nodes.cs
@@ -243,12 +243,20 @@ public override string ToString()
///
public enum NodeType
{
- /// A node for running backtests
- Backtest, //0
- /// A node for running research
- Research, //1
- /// A node for live trading
- Live //2
+ ///
+ /// A node for running backtests (0)
+ ///
+ Backtest,
+
+ ///
+ /// A node for running research (1)
+ ///
+ Research,
+
+ ///
+ /// A node for live trading (2)
+ ///
+ Live
}
///
diff --git a/Common/Api/OptimizationBacktestJsonConverter.cs b/Common/Api/OptimizationBacktestJsonConverter.cs
index a2fea19201a8..5308cbce835a 100644
--- a/Common/Api/OptimizationBacktestJsonConverter.cs
+++ b/Common/Api/OptimizationBacktestJsonConverter.cs
@@ -15,8 +15,8 @@
using System;
using System.Collections.Generic;
-using System.Globalization;
using System.Linq;
+using System.Runtime.CompilerServices;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using QuantConnect.Optimizer.Parameters;
@@ -30,6 +30,43 @@ namespace QuantConnect.Api
///
public class OptimizationBacktestJsonConverter : JsonConverter
{
+ private static Dictionary StatisticsIndices = new()
+ {
+ { PerformanceMetrics.Alpha, 0 },
+ { PerformanceMetrics.AnnualStandardDeviation, 1 },
+ { PerformanceMetrics.AnnualVariance, 2 },
+ { PerformanceMetrics.AverageLoss, 3 },
+ { PerformanceMetrics.AverageWin, 4 },
+ { PerformanceMetrics.Beta, 5 },
+ { PerformanceMetrics.CompoundingAnnualReturn, 6 },
+ { PerformanceMetrics.Drawdown, 7 },
+ { PerformanceMetrics.EstimatedStrategyCapacity, 8 },
+ { PerformanceMetrics.Expectancy, 9 },
+ { PerformanceMetrics.InformationRatio, 10 },
+ { PerformanceMetrics.LossRate, 11 },
+ { PerformanceMetrics.NetProfit, 12 },
+ { PerformanceMetrics.ProbabilisticSharpeRatio, 13 },
+ { PerformanceMetrics.ProfitLossRatio, 14 },
+ { PerformanceMetrics.SharpeRatio, 15 },
+ { PerformanceMetrics.TotalFees, 16 },
+ { PerformanceMetrics.TotalOrders, 17 },
+ { PerformanceMetrics.TrackingError, 18 },
+ { PerformanceMetrics.TreynorRatio, 19 },
+ { PerformanceMetrics.WinRate, 20 },
+ { PerformanceMetrics.SortinoRatio, 21 },
+ { PerformanceMetrics.StartEquity, 22 },
+ { PerformanceMetrics.EndEquity, 23 },
+ { PerformanceMetrics.DrawdownRecovery, 24 },
+ };
+
+ private static string[] StatisticNames { get; } = StatisticsIndices
+ .OrderBy(kvp => kvp.Value)
+ .Select(kvp => kvp.Key)
+ .ToArray();
+
+ // Only 21 Lean statistics where supported when the serialized statistics where a json array
+ private static int ArrayStatisticsCount = 21;
+
///
/// Determines whether this instance can convert the specified object type.
///
@@ -97,25 +134,23 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s
if (!optimizationBacktest.Statistics.IsNullOrEmpty())
{
writer.WritePropertyName("statistics");
- writer.WriteStartArray();
- foreach (var keyValuePair in optimizationBacktest.Statistics.OrderBy(pair => pair.Key))
+ writer.WriteStartObject();
+
+ var customStatisticsNames = new HashSet();
+
+ foreach (var (name, statisticValue, index) in optimizationBacktest.Statistics
+ .Select(kvp => (Name: kvp.Key, kvp.Value, Index: StatisticsIndices.TryGetValue(kvp.Key, out var index) ? index : int.MaxValue))
+ .OrderBy(t => t.Index)
+ .ThenByDescending(t => t.Name))
{
- switch (keyValuePair.Key)
- {
- case PerformanceMetrics.PortfolioTurnover:
- case PerformanceMetrics.SortinoRatio:
- case PerformanceMetrics.StartEquity:
- case PerformanceMetrics.EndEquity:
- case PerformanceMetrics.DrawdownRecovery:
- continue;
- }
- var statistic = keyValuePair.Value.Replace("%", string.Empty);
+ var statistic = statisticValue.Replace("%", string.Empty, StringComparison.InvariantCulture);
if (Currencies.TryParse(statistic, out var result))
{
+ writer.WritePropertyName(index < StatisticsIndices.Count ? index.ToStringInvariant() : name);
writer.WriteValue(result);
}
}
- writer.WriteEndArray();
+ writer.WriteEndObject();
}
if (optimizationBacktest.ParameterSet != null)
@@ -164,34 +199,25 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
Dictionary statistics = default;
if (jStatistics != null)
{
- statistics = new Dictionary
+ if (jStatistics.Type == JTokenType.Array)
{
- { PerformanceMetrics.Alpha, jStatistics[0].Value() },
- { PerformanceMetrics.AnnualStandardDeviation, jStatistics[1].Value() },
- { PerformanceMetrics.AnnualVariance, jStatistics[2].Value() },
- { PerformanceMetrics.AverageLoss, jStatistics[3].Value() },
- { PerformanceMetrics.AverageWin, jStatistics[4].Value() },
- { PerformanceMetrics.Beta, jStatistics[5].Value() },
- { PerformanceMetrics.CompoundingAnnualReturn, jStatistics[6].Value() },
- { PerformanceMetrics.Drawdown, jStatistics[7].Value() },
- { PerformanceMetrics.EstimatedStrategyCapacity, jStatistics[8].Value() },
- { PerformanceMetrics.Expectancy, jStatistics[9].Value() },
- { PerformanceMetrics.InformationRatio, jStatistics[10].Value() },
- { PerformanceMetrics.LossRate, jStatistics[11].Value() },
- { PerformanceMetrics.NetProfit, jStatistics[12].Value() },
- { PerformanceMetrics.ProbabilisticSharpeRatio, jStatistics[13].Value() },
- { PerformanceMetrics.ProfitLossRatio, jStatistics[14].Value() },
- { PerformanceMetrics.SharpeRatio, jStatistics[15].Value() },
- // TODO: Add SortinoRatio
- // TODO: Add StartingEquity
- // TODO: Add EndingEquity
- // TODO: Add DrawdownRecovery
- { PerformanceMetrics.TotalFees, jStatistics[16].Value() },
- { PerformanceMetrics.TotalOrders, jStatistics[17].Value() },
- { PerformanceMetrics.TrackingError, jStatistics[18].Value() },
- { PerformanceMetrics.TreynorRatio, jStatistics[19].Value() },
- { PerformanceMetrics.WinRate, jStatistics[20].Value() },
- };
+ var statsCount = Math.Min(ArrayStatisticsCount, (jStatistics as JArray).Count);
+ statistics = new Dictionary(StatisticsIndices
+ .Where(kvp => kvp.Value < statsCount)
+ .Select(kvp => KeyValuePair.Create(kvp.Key, jStatistics[kvp.Value].Value()))
+ .Where(kvp => kvp.Value != null));
+ }
+ else
+ {
+ statistics = new();
+ foreach (var statistic in jStatistics.Children())
+ {
+ var statisticName = TryConvertToLeanStatisticIndex(statistic.Name, out var index)
+ ? StatisticNames[index]
+ : statistic.Name;
+ statistics[statisticName] = statistic.Value.Value();
+ }
+ }
}
var parameterSet = serializer.Deserialize(jObject["parameterSet"].CreateReader());
@@ -220,5 +246,11 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
return optimizationBacktest;
}
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static bool TryConvertToLeanStatisticIndex(string statistic, out int index)
+ {
+ return int.TryParse(statistic, out index) && index >= 0 && index < StatisticsIndices.Count;
+ }
}
}
diff --git a/Common/Api/Organization.cs b/Common/Api/Organization.cs
index 5244ab90d642..a3fcfaa32fcf 100644
--- a/Common/Api/Organization.cs
+++ b/Common/Api/Organization.cs
@@ -69,6 +69,7 @@ public class DataAgreement
/// DateTime the agreement was signed.
/// Uses EpochSignedTime converted to a standard datetime.
///
+ [JsonIgnore]
public DateTime? SignedTime => EpochSignedTime.HasValue ? DateTimeOffset.FromUnixTimeSeconds(EpochSignedTime.Value).DateTime : null;
///
@@ -108,7 +109,7 @@ public class Product
}
///
- /// QuantConnect ProductItem
+ /// QuantConnect ProductItem
///
public class ProductItem
{
diff --git a/Common/Api/Project.cs b/Common/Api/Project.cs
index c9f437410abf..7a7cb74e22d4 100644
--- a/Common/Api/Project.cs
+++ b/Common/Api/Project.cs
@@ -27,7 +27,7 @@ public class Collaborator
/// User ID
///
[JsonProperty(PropertyName = "uid")]
- public int Uid { get; set; }
+ public int? Uid { get; set; }
///
/// Indicate if the user have live control
@@ -46,7 +46,7 @@ public class Collaborator
/// The user public ID
///
[JsonProperty(PropertyName = "publicId")]
- public string PublicId { get; set; }
+ public string PublicId { get; set; }
///
/// The url of the user profile image
@@ -119,7 +119,7 @@ public class GridChart
/// The chart name
///
[JsonProperty(PropertyName = "chartName")]
- public string ChartName { get; set;}
+ public string ChartName { get; set; }
///
/// Width of the chart
@@ -328,7 +328,7 @@ public class Project : RestResponse
///
/// Configuration of the backtest view grid
///
- [JsonProperty(PropertyName = "grid" )]
+ [JsonProperty(PropertyName = "grid")]
public Grid Grid { get; set; }
///
@@ -365,7 +365,7 @@ public class Project : RestResponse
/// Indicates if the project is running or not
///
[JsonProperty(PropertyName = "codeRunning")]
- public bool CodeRunning { get; set; }
+ public bool CodeRunning { get; set; }
///
/// LEAN environment of the project running on
diff --git a/Common/Brokerages/BrokerageName.cs b/Common/Brokerages/BrokerageName.cs
index 5cfc19b3ee19..7f6edaab7a5e 100644
--- a/Common/Brokerages/BrokerageName.cs
+++ b/Common/Brokerages/BrokerageName.cs
@@ -163,7 +163,7 @@ public enum BrokerageName
/// Transaction and submit/execution rules will use Axos models
///
Axos,
-
+
///
/// Transaction and submit/execution rules will use Coinbase broker's model
///
@@ -192,6 +192,11 @@ public enum BrokerageName
///
/// Transaction and submit/execution rules will use interactive brokers Fix models
///
- InteractiveBrokersFix
+ InteractiveBrokersFix,
+
+ ///
+ /// Transaction and submit/execution rules will use dYdX models
+ ///
+ DYDX
}
}
diff --git a/Common/Brokerages/DelistingNotificationEventArgs.cs b/Common/Brokerages/DelistingNotificationEventArgs.cs
index 118a346b64e5..fbcfbaffbccf 100644
--- a/Common/Brokerages/DelistingNotificationEventArgs.cs
+++ b/Common/Brokerages/DelistingNotificationEventArgs.cs
@@ -35,5 +35,13 @@ public DelistingNotificationEventArgs(Symbol symbol)
{
Symbol = symbol;
}
+
+ ///
+ /// Returns a string describing the delisting notification.
+ ///
+ public override string ToString()
+ {
+ return $"Symbol: {Symbol}";
+ }
}
}
diff --git a/Common/Brokerages/IBrokerageModel.cs b/Common/Brokerages/IBrokerageModel.cs
index a79294ed7ed2..4544c388d8c1 100644
--- a/Common/Brokerages/IBrokerageModel.cs
+++ b/Common/Brokerages/IBrokerageModel.cs
@@ -288,6 +288,9 @@ public static IBrokerageModel Create(IOrderProvider orderProvider, BrokerageName
case BrokerageName.Tastytrade:
return new TastytradeBrokerageModel(accountType);
+ case BrokerageName.DYDX:
+ return new dYdXBrokerageModel(accountType);
+
default:
throw new ArgumentOutOfRangeException(nameof(brokerage), brokerage, null);
}
diff --git a/Common/Brokerages/NewBrokerageOrderNotificationEventArgs.cs b/Common/Brokerages/NewBrokerageOrderNotificationEventArgs.cs
index 8965fd8bd576..f77212acde1f 100644
--- a/Common/Brokerages/NewBrokerageOrderNotificationEventArgs.cs
+++ b/Common/Brokerages/NewBrokerageOrderNotificationEventArgs.cs
@@ -35,5 +35,13 @@ public NewBrokerageOrderNotificationEventArgs(Order order)
{
Order = order;
}
+
+ ///
+ /// Returns a string describing the new brokerage order notification.
+ ///
+ override public string ToString()
+ {
+ return Order.ToString();
+ }
}
}
diff --git a/Common/Brokerages/TradingTechnologiesBrokerageModel.cs b/Common/Brokerages/TradingTechnologiesBrokerageModel.cs
index 28f580039cb2..82912eb470d8 100644
--- a/Common/Brokerages/TradingTechnologiesBrokerageModel.cs
+++ b/Common/Brokerages/TradingTechnologiesBrokerageModel.cs
@@ -140,7 +140,7 @@ public override bool CanSubmitOrder(Security security, Order order, out Brokerag
var stopLimit = order as StopLimitOrder;
if (stopLimit != null)
{
- return IsValidOrderPrices(security, OrderType.StopMarket, stopLimit.Direction, stopLimit.StopPrice, stopLimit.LimitPrice, ref message);
+ return IsValidOrderPrices(security, OrderType.StopLimit, stopLimit.Direction, stopLimit.StopPrice, stopLimit.LimitPrice, ref message);
}
return true;
diff --git a/Common/Brokerages/dYdXBrokerageModel.cs b/Common/Brokerages/dYdXBrokerageModel.cs
new file mode 100644
index 000000000000..d8b342aeddba
--- /dev/null
+++ b/Common/Brokerages/dYdXBrokerageModel.cs
@@ -0,0 +1,168 @@
+/*
+ * 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;
+using System.Collections.Generic;
+using System.Linq;
+using QuantConnect.Benchmarks;
+using QuantConnect.Orders;
+using QuantConnect.Orders.Fees;
+using QuantConnect.Securities;
+using QuantConnect.Securities.CryptoFuture;
+using QuantConnect.Util;
+
+namespace QuantConnect.Brokerages;
+
+public class dYdXBrokerageModel : DefaultBrokerageModel
+{
+ ///
+ /// Gets a map of the default markets to be used for each security type
+ ///
+ public override IReadOnlyDictionary DefaultMarkets { get; } = GetDefaultMarkets(Market.DYDX);
+
+ ///
+ /// Initializes a new instance of the class
+ ///
+ /// The type of account to be modeled, defaults to
+ public dYdXBrokerageModel(AccountType accountType = AccountType.Margin) : base(accountType)
+ {
+ if (accountType != AccountType.Margin)
+ {
+ throw new ArgumentException("dYdXBrokerageModel only supports margin accounts", nameof(accountType));
+ }
+ }
+
+ ///
+ /// Gets a new buying power model for the security, returning the default model with the security's configured leverage.
+ /// For cash accounts, leverage = 1 is used.
+ ///
+ /// The security to get a buying power model for
+ /// The buying power model for this brokerage/security
+ public override IBuyingPowerModel GetBuyingPowerModel(Security security)
+ {
+ return security?.Type switch
+ {
+ SecurityType.CryptoFuture => new SecurityMarginModel(GetLeverage(security)),
+ _ => base.GetBuyingPowerModel(security)
+ };
+ }
+
+ ///
+ /// Provides dYdX fee model
+ ///
+ ///
+ ///
+ public override IFeeModel GetFeeModel(Security security)
+ {
+ return security.Type switch
+ {
+ SecurityType.CryptoFuture => new dYdXFeeModel(),
+ _ => base.GetFeeModel(security)
+ };
+ }
+
+ ///
+ /// Gets a new margin interest rate model for the security
+ ///
+ /// The security to get a margin interest rate model for
+ /// The margin interest rate model for this brokerage
+ public override IMarginInterestRateModel GetMarginInterestRateModel(Security security)
+ {
+ // only applies for perpetual futures
+ return security.Type switch
+ {
+ SecurityType.CryptoFuture => new dYdXFutureMarginInterestRateModel(),
+ _ => base.GetMarginInterestRateModel(security)
+ };
+ }
+
+ ///
+ /// Get the benchmark for this model
+ ///
+ /// SecurityService to create the security with if needed
+ /// The benchmark for this brokerage
+ public override IBenchmark GetBenchmark(SecurityManager securities)
+ {
+ var symbol = Symbol.Create("BTCUSD", SecurityType.CryptoFuture, Market.DYDX);
+ return SecurityBenchmark.CreateInstance(securities, symbol);
+ //todo default conversion?
+ }
+
+ ///
+ /// Returns true if the brokerage could accept this order update. This takes into account
+ /// order type, security type, and order size limits. dYdX can only update inverse, linear, and option orders
+ ///
+ /// The security of the order
+ /// The order to be updated
+ /// The requested update to be made to the order
+ /// If this function returns false, a brokerage message detailing why the order may not be updated
+ /// True if the brokerage could update the order, false otherwise
+ public override bool CanUpdateOrder(Security security, Order order, UpdateOrderRequest request,
+ out BrokerageMessageEvent message)
+ {
+ message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
+ Messages.DefaultBrokerageModel.OrderUpdateNotSupported);
+ return false;
+ }
+
+ ///
+ /// Returns true if the brokerage could accept this order. This takes into account
+ /// order type, security type, and order size limits.
+ ///
+ ///
+ /// For example, a brokerage may have no connectivity at certain times, or an order rate/size limit
+ ///
+ /// The security of the order
+ /// The order to be processed
+ /// If this function returns false, a brokerage message detailing why the order may not be submitted
+ /// True if the brokerage could process the order, false otherwise
+ public override bool CanSubmitOrder(Security security, Order order, out BrokerageMessageEvent message)
+ {
+ if (security.Type != SecurityType.CryptoFuture)
+ {
+ message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
+ Messages.DefaultBrokerageModel.UnsupportedSecurityType(this, security));
+
+ return false;
+ }
+
+ message = null;
+ bool quantityIsValid;
+
+ switch (order)
+ {
+ case StopLimitOrder:
+ case StopMarketOrder:
+ case LimitOrder:
+ case MarketOrder:
+ quantityIsValid = IsValidOrderSize(security, Math.Abs(order.Quantity), out message);
+ break;
+ default:
+ message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
+ Messages.DefaultBrokerageModel.UnsupportedOrderType(this, order,
+ [OrderType.StopMarket, OrderType.StopLimit, OrderType.Market, OrderType.Limit]));
+ return false;
+ }
+
+ return quantityIsValid;
+ }
+
+ private static IReadOnlyDictionary GetDefaultMarkets(string marketName)
+ {
+ var map = DefaultMarketMap.ToDictionary();
+ map[SecurityType.CryptoFuture] = marketName;
+ return map.ToReadOnlyDictionary();
+ }
+}
diff --git a/Common/Currencies.cs b/Common/Currencies.cs
index 81251832ba1b..894693b15232 100644
--- a/Common/Currencies.cs
+++ b/Common/Currencies.cs
@@ -228,7 +228,7 @@ public static class Currencies
};
///
- /// Define some StableCoins that don't have direct pairs for base currencies in our SPDB in Binance market
+ /// Define some StableCoins that don't have direct pairs for base currencies in our SPDB in Bybit market
/// This is because some CryptoExchanges do not define direct pairs with the stablecoins they offer.
///
/// We use this to allow setting cash amounts for these stablecoins without needing a conversion
@@ -246,6 +246,18 @@ public static class Currencies
"DAIUSD"
};
+ ///
+ /// Define some StableCoins that don't have direct pairs for base currencies in our SPDB in dYdX market
+ /// This is because some CryptoExchanges do not define direct pairs with the stablecoins they offer.
+ ///
+ /// We use this to allow setting cash amounts for these stablecoins without needing a conversion
+ /// security.
+ ///
+ private static readonly HashSet _stableCoinsWithoutPairsdYdX = new HashSet
+ {
+ "USDCUSD"
+ };
+
///
/// Dictionary to save StableCoins in different Markets
///
@@ -255,6 +267,7 @@ public static class Currencies
{ Market.Bitfinex , _stableCoinsWithoutPairsBitfinex},
{ Market.Coinbase, _stableCoinsWithoutPairsCoinbase},
{ Market.Bybit , _stableCoinsWithoutPairsBybit},
+ { Market.DYDX , _stableCoinsWithoutPairsdYdX}
};
///
diff --git a/Common/Data/Market/DataDictionary.cs b/Common/Data/Market/DataDictionary.cs
index cd15648d02e4..f41ea0017828 100644
--- a/Common/Data/Market/DataDictionary.cs
+++ b/Common/Data/Market/DataDictionary.cs
@@ -13,10 +13,12 @@
* limitations under the License.
*/
+using Common.Util;
using QuantConnect.Python;
using System;
-using System.Collections;
using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
namespace QuantConnect.Data.Market
{
@@ -24,15 +26,25 @@ namespace QuantConnect.Data.Market
/// Provides a base class for types holding base data instances keyed by symbol
///
[PandasNonExpandable]
- public class DataDictionary : ExtendedDictionary, IDictionary
+ public class DataDictionary : BaseExtendedDictionary
{
- // storage for the data
- private readonly IDictionary _data = new Dictionary();
+ ///
+ /// Used to cache the sorted items in the dictionary.
+ /// We do this instead of using a SortedDictionary to keep the O(1) access time.
+ ///
+ private List> _items;
+ private List _keys;
+ private List _values;
+
+ ///
+ /// Gets or sets the time associated with this collection of data
+ ///
+ public DateTime Time { get; set; }
///
/// Initializes a new instance of the class.
///
- public DataDictionary()
+ public DataDictionary() : base()
{
}
@@ -43,254 +55,174 @@ public DataDictionary()
/// The data source for this data dictionary
/// Delegate used to select a key from the value
public DataDictionary(IEnumerable data, Func keySelector)
+ : base(data, keySelector)
{
- foreach (var datum in data)
- {
- this[keySelector(datum)] = datum;
- }
}
///
/// Initializes a new instance of the class.
///
/// The time this data was emitted.
- public DataDictionary(DateTime time)
+ public DataDictionary(DateTime time) : base()
{
-#pragma warning disable 618 // This assignment is left here until the Time property is removed.
Time = time;
-#pragma warning restore 618
}
///
- /// Gets or sets the time associated with this collection of data
- ///
- public DateTime Time { get; set; }
-
- ///
- /// Returns an enumerator that iterates through the collection.
- ///
- ///
- /// A that can be used to iterate through the collection.
- ///
- /// 1
- public IEnumerator> GetEnumerator()
- {
- return _data.GetEnumerator();
- }
- ///
- /// Returns an enumerator that iterates through a collection.
- ///
- ///
- /// An object that can be used to iterate through the collection.
- ///
- /// 2
- IEnumerator IEnumerable.GetEnumerator()
- {
- return ((IEnumerable)_data).GetEnumerator();
- }
-
- ///
- /// Adds an item to the .
+ /// Gets or sets the element with the specified key.
///
- /// The object to add to the .The is read-only.
- public void Add(KeyValuePair item)
+ public override T this[Symbol symbol]
{
- _data.Add(item);
+ get
+ {
+ T data;
+ if (TryGetValue(symbol, out data))
+ {
+ return data;
+ }
+ CheckForImplicitlyCreatedSymbol(symbol);
+ throw new KeyNotFoundException($"'{symbol}' wasn't found in the {GetType().GetBetterTypeName()} object, likely because there was no-data at this moment in time and it wasn't possible to fillforward historical data. Please check the data exists before accessing it with data.ContainsKey(\"{symbol}\")");
+ }
+ set
+ {
+ _items = null;
+ base[symbol] = value;
+ }
}
///
- /// Removes all items from the .
+ /// Gets the value associated with the specified key.
///
- /// The is read-only.
- public override void Clear()
+ public virtual T GetValue(Symbol key)
{
- _data.Clear();
+ T value;
+ TryGetValue(key, out value);
+ return value;
}
///
- /// Determines whether the contains a specific value.
+ /// Gets all the items in the dictionary
///
- ///
- /// true if is found in the ; otherwise, false.
- ///
- /// The object to locate in the .
- public virtual bool Contains(KeyValuePair item)
+ /// All the items in the dictionary
+ public override IEnumerable> GetItems()
{
- return _data.Contains(item);
+ if (_items == null)
+ {
+ _items = base.GetItems().OrderBy(x => x.Key).ToList();
+ }
+ return _items;
}
///
- /// Copies the elements of the to an , starting at a particular index.
+ /// Gets a collection containing the keys of the dictionary
///
- /// The one-dimensional that is the destination of the elements copied from . The must have zero-based indexing.The zero-based index in at which copying begins. is null. is less than 0.The number of elements in the source is greater than the available space from to the end of the destination .
- public void CopyTo(KeyValuePair[] array, int arrayIndex)
+ public override ICollection Keys
{
- _data.CopyTo(array, arrayIndex);
+ get
+ {
+ if (_keys == null)
+ {
+ _keys = (_items == null ? base.Keys.OrderBy(x => x) : _items.Select(x => x.Key)).ToList();
+ }
+ return _keys;
+ }
}
///
- /// Removes the first occurrence of a specific object from the .
+ /// Gets a collection containing the values of the dictionary
///
- ///
- /// true if was successfully removed from the ; otherwise, false. This method also returns false if is not found in the original .
- ///
- /// The object to remove from the .The is read-only.
- public virtual bool Remove(KeyValuePair item)
+ public override ICollection Values
{
- return _data.Remove(item);
+ get
+ {
+ if (_values == null)
+ {
+ var items = _items == null
+ ? base.GetItems().OrderBy(x => x.Key)
+ : (IEnumerable>)_items;
+ _values = items.Select(x => x.Value).ToList();
+ }
+ return _values;
+ }
}
///
- /// Gets the number of elements contained in the .
+ /// Gets a collection containing the keys in the dictionary
///
- ///
- /// The number of elements contained in the .
- ///
- public override int Count
- {
- get { return _data.Count; }
- }
+ protected override IEnumerable GetKeys => Keys;
///
- /// Gets a value indicating whether the is read-only.
+ /// Gets a collection containing the values in the dictionary
///
- ///
- /// true if the is read-only; otherwise, false.
- ///
- public override bool IsReadOnly
- {
- get { return _data.IsReadOnly; }
- }
+ protected override IEnumerable GetValues => Values;
///
- /// Determines whether the contains an element with the specified key.
+ /// Returns an enumerator that iterates through the dictionary
///
- ///
- /// true if the contains an element with the key; otherwise, false.
- ///
- /// The key to locate in the . is null.
- public override bool ContainsKey(Symbol key)
+ /// An enumerator for the dictionary
+ public override IEnumerator> GetEnumerator()
{
- return _data.ContainsKey(key);
+ return GetItems().GetEnumerator();
}
///
- /// Gets all the items in the dictionary
+ /// Removes all items from the dictionary
///
- /// All the items in the dictionary
- public override IEnumerable> GetItems() => _data;
-
- ///
- /// Adds an element with the provided key and value to the .
- ///
- /// The object to use as the key of the element to add.The object to use as the value of the element to add. is null.An element with the same key already exists in the .The is read-only.
- public virtual void Add(Symbol key, T value)
+ public override void Clear()
{
- _data.Add(key, value);
+ ClearCache();
+ base.Clear();
}
///
- /// Removes the element with the specified key from the .
+ /// Removes the value with the specified key
///
- ///
- /// true if the element is successfully removed; otherwise, false. This method also returns false if was not found in the original .
- ///
- /// The key of the element to remove. is null.The is read-only.
+ /// The key of the element to remove
+ /// true if the element was successfully found and removed; otherwise, false
public override bool Remove(Symbol key)
{
- return _data.Remove(key);
+ ClearCache();
+ return base.Remove(key);
}
///
- /// Gets the value associated with the specified key.
+ /// Removes the first occurrence of a specific object from the dictionary
///
- ///
- /// true if the object that implements contains an element with the specified key; otherwise, false.
- ///
- /// The key whose value to get.When this method returns, the value associated with the specified key, if the key is found; otherwise, the default value for the type of the parameter. This parameter is passed uninitialized. is null.
- public override bool TryGetValue(Symbol key, out T value)
+ /// The key-value pair to remove
+ /// true if the key-value pair was successfully removed; otherwise, false
+ public override bool Remove(KeyValuePair item)
{
- return _data.TryGetValue(key, out value);
+ ClearCache();
+ return base.Remove(item);
}
///
- /// Gets or sets the element with the specified key.
+ /// Adds an element with the provided key and value to the dictionary
///
- ///
- /// The element with the specified key.
- ///
- /// The key of the element to get or set.
- /// is null.
- /// The property is retrieved and is not found.
- /// The property is set and the is read-only.
- public override T this[Symbol symbol]
+ /// The key of the element to add
+ /// The value of the element to add
+ public override void Add(Symbol key, T value)
{
- get
- {
- T data;
- if (TryGetValue(symbol, out data))
- {
- return data;
- }
- CheckForImplicitlyCreatedSymbol(symbol);
- throw new KeyNotFoundException($"'{symbol}' wasn't found in the {GetType().GetBetterTypeName()} object, likely because there was no-data at this moment in time and it wasn't possible to fillforward historical data. Please check the data exists before accessing it with data.ContainsKey(\"{symbol}\")");
- }
- set
- {
- _data[symbol] = value;
- }
+ ClearCache();
+ base.Add(key, value);
}
///
- /// Gets an containing the keys of the .
+ /// Adds an element with the provided key-value pair to the dictionary
///
- ///
- /// An containing the keys of the object that implements .
- ///
- public ICollection Keys
+ /// The key-value pair to add
+ public override void Add(KeyValuePair item)
{
- get { return _data.Keys; }
+ ClearCache();
+ base.Add(item);
}
- ///
- /// Gets an containing the values in the .
- ///
- ///
- /// An containing the values in the object that implements .
- ///
- public ICollection Values
- {
- get { return _data.Values; }
- }
-
- ///
- /// Gets an containing the Symbol objects of the .
- ///
- ///
- /// An containing the Symbol objects of the object that implements .
- ///
- protected override IEnumerable GetKeys => Keys;
-
- ///
- /// Gets an containing the values in the .
- ///
- ///
- /// An containing the values in the object that implements .
- ///
- protected override IEnumerable GetValues => Values;
-
- ///
- /// Gets the value associated with the specified key.
- ///
- /// The key whose value to get.
- ///
- /// The value associated with the specified key, if the key is found; otherwise, the default value for the type of the parameter.
- ///
- public virtual T GetValue(Symbol key)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private void ClearCache()
{
- T value;
- TryGetValue(key, out value);
- return value;
+ _items = null;
+ _keys = null;
+ _values = null;
}
}
diff --git a/Common/Data/Market/FuturesContract.cs b/Common/Data/Market/FuturesContract.cs
index 8bf0e11bfbaa..56918c97f530 100644
--- a/Common/Data/Market/FuturesContract.cs
+++ b/Common/Data/Market/FuturesContract.cs
@@ -80,7 +80,16 @@ public override long Volume
{
return (long)_universeData.Volume;
}
- return (long)(_tradeBar?.Volume ?? 0);
+
+ if (_tradeBar == null && _tradeTick == null)
+ {
+ return 0L;
+ }
+ if (_tradeBar != null)
+ {
+ return (long)(_tradeTick != null && _tradeTick.EndTime > _tradeBar.EndTime ? _tradeTick.Quantity : _tradeBar.Volume);
+ }
+ return (long)_tradeTick.Quantity;
}
}
@@ -101,7 +110,12 @@ public override decimal BidPrice
}
if (_quoteBar != null)
{
- return _quoteTick != null && _quoteTick.EndTime > _quoteBar.EndTime ? _quoteTick.BidPrice : _quoteBar.Bid.Close;
+ var quoteBarPrice = _quoteBar.Bid?.Close ?? decimal.Zero;
+ if (_quoteTick != null)
+ {
+ return _quoteTick.EndTime > _quoteBar.EndTime ? _quoteTick.BidPrice : quoteBarPrice;
+ }
+ return quoteBarPrice;
}
return _quoteTick.BidPrice;
}
@@ -143,7 +157,12 @@ public override decimal AskPrice
}
if (_quoteBar != null)
{
- return _quoteTick != null && _quoteTick.EndTime > _quoteBar.EndTime ? _quoteTick.AskPrice : _quoteBar.Ask.Close;
+ var quoteBarPrice = _quoteBar.Ask?.Close ?? decimal.Zero;
+ if (_quoteTick != null)
+ {
+ return _quoteTick.EndTime > _quoteBar.EndTime ? _quoteTick.AskPrice : quoteBarPrice;
+ }
+ return quoteBarPrice;
}
return _quoteTick.AskPrice;
}
diff --git a/Common/Data/Market/SessionBar.cs b/Common/Data/Market/SessionBar.cs
index b544a17dcaf9..03c050b8b08f 100644
--- a/Common/Data/Market/SessionBar.cs
+++ b/Common/Data/Market/SessionBar.cs
@@ -51,6 +51,23 @@ public class SessionBar : TradeBar
///
public override decimal Close => _bar?.Close ?? 0m;
+ ///
+ /// The closing time of this bar, computed via the Time and Period
+ ///
+ public override DateTime EndTime
+ {
+ get
+ {
+ if (Time == DateTime.MaxValue)
+ {
+ // Prevent overflow from Time + Period when Time is DateTime.MaxValue
+ return Time;
+ }
+
+ return base.EndTime;
+ }
+ }
+
///
/// The period of this session bar
///
diff --git a/Common/Data/Slice.cs b/Common/Data/Slice.cs
index d7009e3342f4..18c5a3ade2fb 100644
--- a/Common/Data/Slice.cs
+++ b/Common/Data/Slice.cs
@@ -54,7 +54,7 @@ public class Slice : ExtendedDictionary, IEnumerable
/// All the data hold in this slice
///
- public List AllData { get; private set; }
+ public IEnumerable AllData { get; private set; }
///
/// Gets the timestamp for this slice of data
@@ -571,19 +571,21 @@ public void MergeSlice(Slice inputSlice)
_symbolChangedEvents = (SymbolChangedEvents)UpdateCollection(_symbolChangedEvents, inputSlice.SymbolChangedEvents);
_marginInterestRates = (MarginInterestRates)UpdateCollection(_marginInterestRates, inputSlice.MarginInterestRates);
- if (inputSlice.AllData.Count != 0)
+ var ourDataList = (List)AllData;
+ var othersDataList = (List)inputSlice.AllData;
+ if (othersDataList.Count != 0)
{
- if (AllData.Count == 0)
+ if (ourDataList.Count == 0)
{
- AllData = inputSlice.AllData;
+ AllData = othersDataList;
_data = inputSlice._data;
}
else
{
// Should keep this._rawDataList last so that selected data points are not overriden
// while creating _data
- inputSlice.AllData.AddRange(AllData);
- AllData = inputSlice.AllData;
+ othersDataList.AddRange(ourDataList);
+ AllData = othersDataList;
_data = new Lazy>(() => CreateDynamicDataDictionary(AllData));
}
}
diff --git a/Common/Data/SubscriptionDataConfigExtensions.cs b/Common/Data/SubscriptionDataConfigExtensions.cs
index d87c83a5ca02..2a47c5788f50 100644
--- a/Common/Data/SubscriptionDataConfigExtensions.cs
+++ b/Common/Data/SubscriptionDataConfigExtensions.cs
@@ -1,4 +1,4 @@
-/*
+/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
@@ -160,6 +160,14 @@ public static bool EmitSplitsAndDividends(this SubscriptionDataConfig config)
return !config.IsCustomData && !config.Symbol.Value.Contains("UNIVERSE") && config.SecurityType == SecurityType.Equity;
}
+ ///
+ /// True if this configuration is associated with an asset which can have delisting events
+ ///
+ public static bool CanBeDelisted(this SubscriptionDataConfig config)
+ {
+ return config.SecurityType.IsOption() || config.SecurityType == SecurityType.Future || config.SecurityType == SecurityType.Equity;
+ }
+
///
/// Initializes a new instance of the type defined in with the symbol properly set
///
diff --git a/Common/Data/SubscriptionManager.cs b/Common/Data/SubscriptionManager.cs
index eb27871e039e..682f79be85ac 100644
--- a/Common/Data/SubscriptionManager.cs
+++ b/Common/Data/SubscriptionManager.cs
@@ -216,11 +216,10 @@ public void AddConsolidator(Symbol symbol, IDataConsolidator consolidator, TickT
/// The custom python consolidator
public void AddConsolidator(Symbol symbol, PyObject pyConsolidator)
{
- if (!pyConsolidator.TryConvert(out IDataConsolidator consolidator))
- {
- consolidator = new DataConsolidatorPythonWrapper(pyConsolidator);
- }
-
+ var consolidator = PythonUtil.CreateInstanceOrWrapper(
+ pyConsolidator,
+ py => new DataConsolidatorPythonWrapper(py)
+ );
AddConsolidator(symbol, consolidator);
}
diff --git a/Common/Exceptions/StackExceptionInterpreter.cs b/Common/Exceptions/StackExceptionInterpreter.cs
index 04892d06f365..315a2d612db4 100644
--- a/Common/Exceptions/StackExceptionInterpreter.cs
+++ b/Common/Exceptions/StackExceptionInterpreter.cs
@@ -15,6 +15,7 @@
using System;
using System.Linq;
+using QuantConnect.Util;
using System.Reflection;
using QuantConnect.Logging;
using System.Collections.Generic;
@@ -32,7 +33,7 @@ public class StackExceptionInterpreter : IExceptionInterpreter
/// Stack interpreter instance
///
public static readonly Lazy Instance = new Lazy(
- () => StackExceptionInterpreter.CreateFromAssemblies(AppDomain.CurrentDomain.GetAssemblies()));
+ () => StackExceptionInterpreter.CreateFromAssemblies());
///
/// Determines the order that an instance of this class should be called
@@ -111,23 +112,15 @@ public string GetExceptionMessageHeader(Exception exception)
///
/// Creates a new by loading implementations with default constructors from the specified assemblies
///
- /// The assemblies to scan
/// A new containing interpreters from the specified assemblies
- public static StackExceptionInterpreter CreateFromAssemblies(IEnumerable assemblies)
+ public static StackExceptionInterpreter CreateFromAssemblies()
{
var interpreters =
- from assembly in assemblies.Where(x =>
- (!x.FullName?.StartsWith("System.", StringComparison.InvariantCultureIgnoreCase) ?? false)
- && (!x.FullName?.StartsWith("Microsoft.", StringComparison.InvariantCultureIgnoreCase) ?? false))
- from type in assembly.GetTypes()
- // ignore non-public and non-instantiable abstract types
- where type.IsPublic && !type.IsAbstract
// type implements IExceptionInterpreter
- where typeof(IExceptionInterpreter).IsAssignableFrom(type)
- // type is not mocked with MOQ library
- where type.FullName != null && !type.FullName.StartsWith("Castle.Proxies.ObjectProxy", StringComparison.InvariantCultureIgnoreCase)
+ from type in Composer.Instance.GetExportedTypes()
+ // ignore non-public and non-instantiable abstract types
// type has default parameterless ctor
- where type.GetConstructor(new Type[0]) != null
+ where type.IsPublic && !type.IsAbstract && type.GetConstructor([]) != null
// provide guarantee of deterministic ordering
orderby type.FullName
select (IExceptionInterpreter) Activator.CreateInstance(type);
diff --git a/Common/Extensions.cs b/Common/Extensions.cs
index 9ecf5dcc33ca..0c45efb93aa1 100644
--- a/Common/Extensions.cs
+++ b/Common/Extensions.cs
@@ -60,6 +60,8 @@
using QuantConnect.Statistics;
using Newtonsoft.Json.Linq;
using QuantConnect.Orders.Fees;
+using Newtonsoft.Json.Serialization;
+using QuantConnect.Api;
namespace QuantConnect
{
@@ -87,6 +89,22 @@ private static readonly Dictionary PythonActivators
///
private static readonly ZoneLocalMappingResolver _mappingResolver = Resolvers.CreateMappingResolver(Resolvers.ReturnLater, Resolvers.ReturnStartOfIntervalAfter);
+ ///
+ /// Json converter deserializer for streams
+ ///
+ private static readonly JsonSerializer JsonSerializer = new()
+ {
+ Converters = { new LiveAlgorithmResultsJsonConverter(), new OrderJsonConverter() },
+ ContractResolver = new DefaultContractResolver
+ {
+ NamingStrategy = new CamelCaseNamingStrategy
+ {
+ ProcessDictionaryKeys = false,
+ OverrideSpecifiedNames = true
+ }
+ }
+ };
+
///
/// The offset span from the market close to liquidate or exercise a security on the delisting date
///
@@ -262,33 +280,54 @@ public static List DeserializeList(this string jsonArray)
///
/// The http client to use
/// The url to download data from
+ /// The downloaded data
+ /// The request status code
/// Add custom headers for the request
- public static string DownloadData(this HttpClient client, string url, Dictionary headers = null)
+ public static bool TryDownloadData(this HttpClient client, string url, out string data, out HttpStatusCode? statusCode, Dictionary headers = null)
{
+ data = null;
+ statusCode = null;
+ using var request = new HttpRequestMessage(HttpMethod.Get, url);
if (headers != null)
{
foreach (var kvp in headers)
{
- client.DefaultRequestHeaders.Add(kvp.Key, kvp.Value);
+ request.Headers.TryAddWithoutValidation(kvp.Key, kvp.Value);
}
}
try
{
- using (var response = client.GetAsync(url).Result)
+ using var response = client.SendAsync(request).SynchronouslyAwaitTaskResult();
+ statusCode = response.StatusCode;
+
+ if (!response.IsSuccessStatusCode)
{
- using (var content = response.Content)
- {
- return content.ReadAsStringAsync().Result;
- }
+ Log.Error($"DownloadData(): {Messages.Extensions.DownloadDataFailed(url)}. Status code: {response.StatusCode}");
+ return false;
}
+
+ data = response.Content.ReadAsStringAsync().SynchronouslyAwaitTaskResult();
+ return true;
}
catch (WebException ex)
{
Log.Error(ex, $"DownloadData(): {Messages.Extensions.DownloadDataFailed(url)}");
- return null;
+ return false;
}
}
+ ///
+ /// Helper method to download a provided url as a string
+ ///
+ /// The http client to use
+ /// The url to download data from
+ /// Add custom headers for the request
+ public static string DownloadData(this HttpClient client, string url, Dictionary headers = null)
+ {
+ client.TryDownloadData(url, out var data, out _, headers);
+ return data;
+ }
+
///
/// Helper method to download a provided url as a string
///
@@ -903,6 +942,62 @@ public static byte[] GetBytes(this Stream stream)
return memoryStream.ToArray();
}
+ ///
+ /// Deserialize a json stream into an object of type T
+ ///
+ /// The stream to deserialize
+ /// The json serializer to use
+ /// Whether to leave the source stream open
+ /// The deserialized object
+ public static T DeserializeJson(this Stream stream, JsonSerializer serializer = null, bool leaveOpen = true)
+ {
+ using var streamReader = new StreamReader(stream, leaveOpen: leaveOpen);
+ using var jsonReader = new JsonTextReader(streamReader);
+ return (serializer ?? JsonSerializer).Deserialize(jsonReader);
+ }
+
+ ///
+ /// Deserialize a json stream into an object of type T
+ ///
+ /// The string to deserialize
+ /// The json serializer to use
+ /// The deserialized object
+ public static T DeserializeJson(this string content, JsonSerializer serializer = null)
+ {
+ using var stringReader = new StringReader(content);
+ using var jsonReader = new JsonTextReader(stringReader);
+ return (serializer ?? JsonSerializer).Deserialize(jsonReader);
+ }
+
+ ///
+ /// Serialize an object of type T into a json stream
+ ///
+ /// The object to serialize
+ /// The stream to serialize the object to
+ /// The json serializer to use
+ public static void SerializeJsonToStream(this T value, Stream target, JsonSerializer serializer = null)
+ {
+ using var writer = new StreamWriter(target, leaveOpen: true);
+ using var jsonWriter = new JsonTextWriter(writer);
+ (serializer ?? JsonSerializer).Serialize(jsonWriter, value);
+ jsonWriter.Flush();
+ target.Position = 0;
+ }
+
+ ///
+ /// Serialize an object of type T into a json stream
+ ///
+ /// The object to serialize
+ /// The json serializer to use
+ /// The serialized string
+ public static string SerializeJsonToString(this T value, JsonSerializer serializer = null)
+ {
+ using var stringWriter = new StringWriter();
+ using var jsonWriter = new JsonTextWriter(stringWriter);
+ (serializer ?? JsonSerializer).Serialize(jsonWriter, value);
+ return stringWriter.ToString();
+ }
+
///
/// Extentsion method to clear all items from a thread safe queue
///
diff --git a/Common/Global.cs b/Common/Global.cs
index c03edebed771..60fd027d4411 100644
--- a/Common/Global.cs
+++ b/Common/Global.cs
@@ -443,19 +443,39 @@ public enum AccountType
///
public enum MarketDataType
{
+ ///
/// Base market data type (0)
+ ///
Base,
+
+ ///
/// TradeBar market data type (OHLC summary bar) (1)
+ ///
TradeBar,
+
+ ///
/// Tick market data type (price-time pair) (2)
+ ///
Tick,
+
+ ///
/// Data associated with an instrument (3)
+ ///
Auxiliary,
+
+ ///
/// QuoteBar market data type (4) [Bid(OHLC), Ask(OHLC) and Mid(OHLC) summary bar]
+ ///
QuoteBar,
+
+ ///
/// Option chain data (5)
+ ///
OptionChain,
+
+ ///
/// Futures chain data (6)
+ ///
FuturesChain
}
@@ -464,13 +484,24 @@ public enum MarketDataType
///
public enum DataFeedEndpoint
{
+ ///
/// Backtesting Datafeed Endpoint (0)
+ ///
Backtesting,
+
+ ///
/// Loading files off the local system (1)
+ ///
FileSystem,
+
+ ///
/// Getting datafeed from a QC-Live-Cloud (2)
+ ///
LiveTrading,
+
+ ///
/// Database (3)
+ ///
Database
}
@@ -479,10 +510,14 @@ public enum DataFeedEndpoint
///
public enum StoragePermissions
{
+ ///
/// Public Storage Permissions (0)
+ ///
Public,
+ ///
/// Authenticated Read Storage Permissions (1)
+ ///
Authenticated
}
@@ -492,11 +527,19 @@ public enum StoragePermissions
/// QuantConnect currently only has trade, quote, open interest tick data.
public enum TickType
{
+ ///
/// Trade type tick object (0)
- Trade ,
+ ///
+ Trade,
+
+ ///
/// Quote type tick object (1)
+ ///
Quote,
+
+ ///
/// Open Interest type tick object (for options, futures) (2)
+ ///
OpenInterest
}
@@ -538,15 +581,29 @@ public enum SplitType
/// Always sort the enum from the smallest to largest resolution
public enum Resolution
{
+ ///
/// Tick Resolution (0)
+ ///
Tick,
+
+ ///
/// Second Resolution (1)
+ ///
Second,
+
+ ///
/// Minute Resolution (2)
+ ///
Minute,
+
+ ///
/// Hour Resolution (3)
+ ///
Hour,
+
+ ///
/// Daily Resolution (4)
+ ///
Daily
}
@@ -662,29 +719,64 @@ public AlgorithmControl()
///
public enum AlgorithmStatus
{
+ ///
/// Error compiling algorithm at start (0)
+ ///
DeployError,
+
+ ///
/// Waiting for a server (1)
+ ///
InQueue,
+
+ ///
/// Running algorithm (2)
+ ///
Running,
+
+ ///
/// Stopped algorithm or exited with runtime errors (3)
+ ///
Stopped,
+
+ ///
/// Liquidated algorithm (4)
+ ///
Liquidated,
+
+ ///
/// Algorithm has been deleted (5)
+ ///
Deleted,
+
+ ///
/// Algorithm completed running (6)
+ ///
Completed,
+
+ ///
/// Runtime Error Stoped Algorithm (7)
+ ///
RuntimeError,
+
+ ///
/// Error in the algorithm id (not used) (8)
+ ///
Invalid,
+
+ ///
/// The algorithm is logging into the brokerage (9)
+ ///
LoggingIn,
+
+ ///
/// The algorithm is initializing (10)
+ ///
Initializing,
+
+ ///
/// History status update (11)
+ ///
History
}
@@ -745,33 +837,74 @@ public enum WritePolicy
///
public enum Period
{
+ ///
/// Period Short Codes - 10
+ ///
TenSeconds = 10,
+
+ ///
/// Period Short Codes - 30 Second
+ ///
ThirtySeconds = 30,
+
+ ///
/// Period Short Codes - 60 Second
+ ///
OneMinute = 60,
+
+ ///
/// Period Short Codes - 120 Second
+ ///
TwoMinutes = 120,
+
+ ///
/// Period Short Codes - 180 Second
+ ///
ThreeMinutes = 180,
+
+ ///
/// Period Short Codes - 300 Second
+ ///
FiveMinutes = 300,
+
+ ///
/// Period Short Codes - 600 Second
+ ///
TenMinutes = 600,
+
+ ///
/// Period Short Codes - 900 Second
+ ///
FifteenMinutes = 900,
+
+ ///
/// Period Short Codes - 1200 Second
+ ///
TwentyMinutes = 1200,
+
+ ///
/// Period Short Codes - 1800 Second
+ ///
ThirtyMinutes = 1800,
+
+ ///
/// Period Short Codes - 3600 Second
+ ///
OneHour = 3600,
+
+ ///
/// Period Short Codes - 7200 Second
+ ///
TwoHours = 7200,
+
+ ///
/// Period Short Codes - 14400 Second
+ ///
FourHours = 14400,
+
+ ///
/// Period Short Codes - 21600 Second
+ ///
SixHours = 21600
}
diff --git a/Common/Interfaces/IAlgorithm.cs b/Common/Interfaces/IAlgorithm.cs
index 4fb640376b27..4534c2fd6eed 100644
--- a/Common/Interfaces/IAlgorithm.cs
+++ b/Common/Interfaces/IAlgorithm.cs
@@ -33,6 +33,7 @@
using QuantConnect.Algorithm.Framework.Alphas;
using QuantConnect.Algorithm.Framework.Alphas.Analysis;
using QuantConnect.Commands;
+using Common.Util;
namespace QuantConnect.Interfaces
{
@@ -429,7 +430,7 @@ InsightManager Insights
///
/// Gets a read-only dictionary with all current parameters
///
- IReadOnlyDictionary GetParameters();
+ ReadOnlyExtendedDictionary GetParameters();
///
/// Gets the parameter with the specified name. If a parameter with the specified name does not exist,
@@ -839,9 +840,23 @@ Security AddSecurity(Symbol symbol, Resolution? resolution = null, bool fillForw
/// Get the last known price using the history provider.
/// Useful for seeding securities with the correct price
///
- /// object for which to retrieve historical data
+ /// The symbol for which to retrieve historical data
/// A single object with the last known price
- BaseData GetLastKnownPrice(Security security);
+ BaseData GetLastKnownPrice(Symbol symbol);
+
+ ///
+ /// Yields data to warmup a security for all it's subscribed data types
+ ///
+ /// The symbol for which to retrieve historical data
+ /// Securities historical data
+ IEnumerable GetLastKnownPrices(Symbol symbol);
+
+ ///
+ /// Yields data to warm up multiple securities for all their subscribed data types
+ ///
+ /// The symbols we want to get seed data for
+ /// Securities historical data
+ DataDictionary> GetLastKnownPrices(IEnumerable symbols);
///
/// Set the runtime error
diff --git a/Common/Interfaces/IAlgorithmSettings.cs b/Common/Interfaces/IAlgorithmSettings.cs
index e30072063e1f..7e71531f1078 100644
--- a/Common/Interfaces/IAlgorithmSettings.cs
+++ b/Common/Interfaces/IAlgorithmSettings.cs
@@ -143,5 +143,10 @@ public interface IAlgorithmSettings
/// Performance tracking sample period to use if any, useful to debug performance issues
///
TimeSpan PerformanceSamplePeriod { get; set; }
+
+ ///
+ /// Determines whether to seed initial prices for all selected and manually added securities.
+ ///
+ bool SeedInitialPrices { get; set; }
}
}
diff --git a/Common/Interfaces/ISecurityService.cs b/Common/Interfaces/ISecurityService.cs
index 5d7f362f389d..466fcb8c7cc1 100644
--- a/Common/Interfaces/ISecurityService.cs
+++ b/Common/Interfaces/ISecurityService.cs
@@ -34,7 +34,8 @@ Security CreateSecurity(Symbol symbol,
List subscriptionDataConfigList,
decimal leverage = 0,
bool addToSymbolCache = true,
- Security underlying = null);
+ Security underlying = null,
+ bool seedSecurity = true);
///
/// Creates a new security
@@ -45,7 +46,8 @@ Security CreateSecurity(Symbol symbol,
SubscriptionDataConfig subscriptionDataConfig,
decimal leverage = 0,
bool addToSymbolCache = true,
- Security underlying = null);
+ Security underlying = null,
+ bool seedSecurity = true);
///
/// Creates a new benchmark security
diff --git a/Common/Market.cs b/Common/Market.cs
index b2a1692cbd68..e4745023ce2f 100644
--- a/Common/Market.cs
+++ b/Common/Market.cs
@@ -70,7 +70,8 @@ public static class Market
Tuple.Create(Coinbase, 38),
Tuple.Create(InteractiveBrokers, 39),
Tuple.Create(EUREX, 40),
- Tuple.Create(OSE, 41)
+ Tuple.Create(OSE, 41),
+ Tuple.Create(DYDX, 42)
};
static Market()
@@ -261,6 +262,11 @@ static Market()
///
public const string InteractiveBrokers = "interactivebrokers";
+ ///
+ /// dYdX market
+ ///
+ public const string DYDX = "dydx";
+
///
/// Adds the specified market to the map of available markets with the specified identifier.
///
diff --git a/Common/Messages/Messages.Orders.cs b/Common/Messages/Messages.Orders.cs
index 1562593b46ce..47033d5192eb 100644
--- a/Common/Messages/Messages.Orders.cs
+++ b/Common/Messages/Messages.Orders.cs
@@ -527,7 +527,7 @@ public static string ToString(Orders.SubmitOrderRequest request)
{
// create a proxy order object to steal its ToString method
var proxy = Orders.Order.CreateOrder(request);
- return Invariant($"{request.Time} UTC: Submit Order: ({request.OrderId}) - {proxy} {request.Tag} Status: {request.Status}");
+ return Invariant($"{request.Time} UTC: Submit Order: ({request.OrderId}) - {proxy} {request.Tag} Status: {request.Status} Async: {request.Asynchronous}");
}
}
diff --git a/Common/Orders/Fees/dYdXFeeModel.cs b/Common/Orders/Fees/dYdXFeeModel.cs
new file mode 100644
index 000000000000..4a9163c5aa74
--- /dev/null
+++ b/Common/Orders/Fees/dYdXFeeModel.cs
@@ -0,0 +1,93 @@
+/*
+ * 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 QuantConnect.Securities;
+using QuantConnect.Util;
+
+namespace QuantConnect.Orders.Fees;
+
+///
+/// dYdX fee model implementation
+///
+public class dYdXFeeModel : FeeModel
+{
+ ///
+ /// Tier 1 maker fees
+ /// https://dydx.trade/portfolio/fees
+ ///
+ private const decimal MakerTier1Fee = 0.0001m;
+
+ ///
+ /// Tier 1 taker fees
+ /// https://dydx.trade/portfolio/fees
+ ///
+ private const decimal TakerTier1Fee = 0.0005m;
+
+ private readonly decimal _makerFee;
+ private readonly decimal _takerFee;
+
+ ///
+ /// Creates Binance fee model setting fees values
+ ///
+ /// Maker fee value
+ /// Taker fee value
+ public dYdXFeeModel(decimal mFee = MakerTier1Fee, decimal tFee = TakerTier1Fee)
+ {
+ _makerFee = mFee;
+ _takerFee = tFee;
+ }
+
+ ///
+ /// Gets the order fee associated with the specified order.
+ ///
+ /// A object
+ /// containing the security and order
+ /// The cost of the order in a instance
+ public override OrderFee GetOrderFee(OrderFeeParameters parameters)
+ {
+ var security = parameters.Security;
+ var order = parameters.Order;
+
+ var fee = GetFee(order);
+ var positionValue = security.Holdings.GetQuantityValue(order.AbsoluteQuantity, security.Price);
+
+ return new OrderFee(new CashAmount(positionValue.Amount * fee, positionValue.Cash.Symbol));
+ }
+
+ ///
+ /// Gets the fee factor for the given order
+ ///
+ /// The order to get the fee factor for
+ /// The fee factor for the given order
+ protected virtual decimal GetFee(Order order)
+ {
+ return GetFee(order, _makerFee, _takerFee);
+ }
+
+ private static decimal GetFee(Order order, decimal makerFee, decimal takerFee)
+ {
+ // apply fee factor, currently we do not model 30-day volume, so we use the first tier
+ var fee = takerFee;
+ var props = order.Properties as dYdXOrderProperties;
+
+ if (order.Type == OrderType.Limit && (props is { PostOnly: true } || !order.IsMarketable))
+ {
+ // limit order posted to the order book
+ fee = makerFee;
+ }
+
+ return fee;
+ }
+}
diff --git a/Common/Orders/dYdXOrderProperties.cs b/Common/Orders/dYdXOrderProperties.cs
new file mode 100644
index 000000000000..3f646c9a9277
--- /dev/null
+++ b/Common/Orders/dYdXOrderProperties.cs
@@ -0,0 +1,86 @@
+/*
+ * 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 QuantConnect.Interfaces;
+
+namespace QuantConnect.Orders
+{
+ ///
+ /// Contains additional properties and settings for an order submitted to Binance brokerage
+ ///
+ public class dYdXOrderProperties : OrderProperties
+ {
+ ///
+ /// This flag will ensure the order executes only as a maker (no fee) order.
+ /// If part of the order results in taking liquidity rather than providing,
+ /// it will be rejected and no part of the order will execute.
+ /// Note: this flag is only applied to Limit orders.
+ ///
+ public bool PostOnly
+ {
+ get;
+ set
+ {
+ if (value && IOC)
+ {
+ throw new System.InvalidOperationException("Cannot set PostOnly when IOC is already set. Only one execution type can be active at a time.");
+ }
+ field = value;
+ }
+ }
+
+ ///
+ /// Enforces that an order only be placed
+ /// on the book as a maker order. Note this means that validators will cancel
+ /// any newly placed post only orders that would cross with other maker
+ /// orders.
+ ///
+ public bool IOC
+ {
+ get;
+ set
+ {
+ if (value && PostOnly)
+ {
+ throw new System.InvalidOperationException("Cannot set IOC when PostOnly is already set. Only one execution type can be active at a time.");
+ }
+ field = value;
+ }
+ }
+
+ ///
+ /// The maximum amount of gas to use for the order.
+ ///
+ public ulong GasLimit { get; set; } = 1_000_000;
+
+ ///
+ /// If you send a reduce-only order, it will only trade if it decreases your position size.
+ ///
+ public bool ReduceOnly { get; set; }
+
+ ///
+ /// The block height at which the order expires.
+ ///
+ public uint GoodTilBlockOffset { get; set; } = 20;
+
+ ///
+ /// Returns a new instance clone of this object
+ ///
+ public override IOrderProperties Clone()
+ {
+ return (dYdXOrderProperties)MemberwiseClone();
+ }
+ }
+}
diff --git a/Common/Packets/BacktestResultPacket.cs b/Common/Packets/BacktestResultPacket.cs
index 7a6e2317dd78..6a33c47e1465 100644
--- a/Common/Packets/BacktestResultPacket.cs
+++ b/Common/Packets/BacktestResultPacket.cs
@@ -208,11 +208,6 @@ public class BacktestResult : Result
///
public Dictionary RollingWindow { get; set; } = new Dictionary();
- ///
- /// Rolling window detailed statistics.
- ///
- public AlgorithmPerformance TotalPerformance { get; set; }
-
///
/// Default Constructor
///
@@ -226,7 +221,6 @@ public BacktestResult()
public BacktestResult(BacktestResultParameters parameters) : base(parameters)
{
RollingWindow = parameters.RollingWindow;
- TotalPerformance = parameters.TotalPerformance;
}
}
} // End of Namespace:
diff --git a/Common/Packets/BacktestResultParameters.cs b/Common/Packets/BacktestResultParameters.cs
index 31a89506876a..7481750c5617 100644
--- a/Common/Packets/BacktestResultParameters.cs
+++ b/Common/Packets/BacktestResultParameters.cs
@@ -18,7 +18,6 @@
using QuantConnect.Orders;
using QuantConnect.Statistics;
using System.Collections.Generic;
-using QuantConnect.Securities.Positions;
namespace QuantConnect.Packets
{
@@ -32,10 +31,6 @@ public class BacktestResultParameters : BaseResultParameters
///
public Dictionary RollingWindow { get; set; }
- ///
- /// Rolling window detailed statistics.
- ///
- public AlgorithmPerformance TotalPerformance { get; set; }
///
/// Creates a new instance
///
@@ -49,10 +44,9 @@ public BacktestResultParameters(IDictionary charts,
AlgorithmPerformance totalPerformance = null,
AlgorithmConfiguration algorithmConfiguration = null,
IDictionary state = null)
- : base(charts, orders, profitLoss, statistics, runtimeStatistics, orderEvents, algorithmConfiguration, state)
+ : base(charts, orders, profitLoss, statistics, runtimeStatistics, orderEvents, totalPerformance, algorithmConfiguration, state)
{
RollingWindow = rollingWindow;
- TotalPerformance = totalPerformance;
}
}
}
diff --git a/Common/Packets/BaseResultParameters.cs b/Common/Packets/BaseResultParameters.cs
index fcf6cfe2d8c3..e75c7001c412 100644
--- a/Common/Packets/BaseResultParameters.cs
+++ b/Common/Packets/BaseResultParameters.cs
@@ -14,8 +14,9 @@
*
*/
-using System;
using QuantConnect.Orders;
+using QuantConnect.Statistics;
+using System;
using System.Collections.Generic;
namespace QuantConnect.Packets
@@ -65,6 +66,11 @@ public class BaseResultParameters
///
public AlgorithmConfiguration AlgorithmConfiguration { get; set; }
+ ///
+ /// Rolling window detailed statistics.
+ ///
+ public AlgorithmPerformance TotalPerformance { get; set; }
+
///
/// Creates a new instance
///
@@ -74,6 +80,7 @@ public BaseResultParameters(IDictionary charts,
IDictionary statistics,
IDictionary runtimeStatistics,
List orderEvents,
+ AlgorithmPerformance totalPerformance = null,
AlgorithmConfiguration algorithmConfiguration = null,
IDictionary state = null)
{
@@ -85,6 +92,7 @@ public BaseResultParameters(IDictionary charts,
OrderEvents = orderEvents;
AlgorithmConfiguration = algorithmConfiguration;
State = state;
+ TotalPerformance = totalPerformance;
}
}
}
diff --git a/Common/Packets/LiveResultPacket.cs b/Common/Packets/LiveResultPacket.cs
index f054c61beb87..38d032328a62 100644
--- a/Common/Packets/LiveResultPacket.cs
+++ b/Common/Packets/LiveResultPacket.cs
@@ -14,13 +14,13 @@
*
*/
-using System;
-using System.Linq;
using Newtonsoft.Json;
-using QuantConnect.Orders;
using QuantConnect.Logging;
+using QuantConnect.Orders;
using QuantConnect.Securities;
+using System;
using System.Collections.Generic;
+using System.Linq;
namespace QuantConnect.Packets
{
@@ -109,7 +109,7 @@ public static LiveResultPacket CreateEmpty(LiveNodePacket job)
return new LiveResultPacket(job, new LiveResult(new LiveResultParameters(
new Dictionary(), new Dictionary(), new Dictionary(),
new Dictionary(), new CashBook(), new Dictionary(),
- new SortedDictionary(), new List(), new Dictionary(),
+ new SortedDictionary(), new List(), null, new Dictionary(),
new AlgorithmConfiguration(), new Dictionary())));
}
} // End Queue Packet:
diff --git a/Common/Packets/LiveResultParameters.cs b/Common/Packets/LiveResultParameters.cs
index cc4b4a3b2b2f..60e14fa246ea 100644
--- a/Common/Packets/LiveResultParameters.cs
+++ b/Common/Packets/LiveResultParameters.cs
@@ -14,9 +14,10 @@
*
*/
-using System;
using QuantConnect.Orders;
using QuantConnect.Securities;
+using QuantConnect.Statistics;
+using System;
using System.Collections.Generic;
namespace QuantConnect.Packets
@@ -52,10 +53,11 @@ public LiveResultParameters(IDictionary charts,
IDictionary statistics,
IDictionary runtimeStatistics,
List orderEvents,
+ AlgorithmPerformance totalPerformance = null,
IDictionary serverStatistics = null,
AlgorithmConfiguration algorithmConfiguration = null,
IDictionary state = null)
- : base(charts, orders, profitLoss, statistics, runtimeStatistics, orderEvents, algorithmConfiguration, state)
+ : base(charts, orders, profitLoss, statistics, runtimeStatistics, orderEvents, totalPerformance, algorithmConfiguration, state)
{
Holdings = holdings;
CashBook = cashBook;
diff --git a/Common/Packets/Packet.cs b/Common/Packets/Packet.cs
index 831d0c44a195..f4b308663cd6 100644
--- a/Common/Packets/Packet.cs
+++ b/Common/Packets/Packet.cs
@@ -51,160 +51,264 @@ public Packet(PacketType type)
[JsonConverter(typeof(StringEnumConverter))]
public enum PacketType
{
+ ///
/// Default, unset:
+ ///
None,
+ ///
/// Base type for backtest and live work
+ ///
AlgorithmNode,
+ ///
/// Autocomplete Work Packet
+ ///
AutocompleteWork,
+ ///
/// Result of the Autocomplete Job:
+ ///
AutocompleteResult,
+ ///
/// Controller->Backtest Node Packet:
+ ///
BacktestNode,
+ ///
/// Packet out of backtest node:
+ ///
BacktestResult,
+ ///
/// API-> Controller Work Packet:
+ ///
BacktestWork,
+ ///
/// Controller -> Live Node Packet:
+ ///
LiveNode,
+ ///
/// Live Node -> User Packet:
+ ///
LiveResult,
+ ///
/// API -> Controller Packet:
+ ///
LiveWork,
+ ///
/// Node -> User Algo Security Types
+ ///
SecurityTypes,
+ ///
/// Controller -> User Error in Backtest Settings:
+ ///
BacktestError,
+ ///
/// Nodes -> User Algorithm Status Packet:
+ ///
AlgorithmStatus,
+ ///
/// API -> Compiler Work Packet:
+ ///
BuildWork,
+ ///
/// Compiler -> User Build Success
+ ///
BuildSuccess,
+ ///
/// Compiler -> User, Compile Error
+ ///
BuildError,
+ ///
/// Node -> User Algorithm Runtime Error
+ ///
RuntimeError,
+ ///
/// Error is an internal handled error packet inside users algorithm
+ ///
HandledError,
+ ///
/// Nodes -> User Log Message
+ ///
Log,
+ ///
/// Nodes -> User Debug Message
+ ///
Debug,
+ ///
/// Nodes -> User, Order Update Event
+ ///
OrderEvent,
+ ///
/// Boolean true/false success
+ ///
Success,
+ ///
/// History live job packets
+ ///
History,
+ ///
/// Result from a command
+ ///
CommandResult,
+ ///
/// Hook from git hub
+ ///
GitHubHook,
+ ///
/// Documentation result from docs server
+ ///
DocumentationResult,
+ ///
/// Documentation request to the docs server
+ ///
Documentation,
+ ///
/// Debug packet generated by Lean
+ ///
SystemDebug,
+ ///
/// Packet containing insights generated by the algorithm
+ ///
AlphaResult,
+ ///
/// Alpha API -> Controller packet
+ ///
AlphaWork,
+ ///
/// Alpha Controller -> Alpha Node packet
+ ///
AlphaNode,
+ ///
/// Packet containing list of algorithms to run as a regression test
+ ///
RegressionAlgorithm,
+ ///
/// Packet containing a heartbeat
+ ///
AlphaHeartbeat,
+ ///
/// Used when debugging to send status updates
+ ///
DebuggingStatus,
+ ///
/// Optimization Node Packet:
+ ///
OptimizationNode,
+ ///
/// Optimization Estimate Packet:
+ ///
OptimizationEstimate,
+ ///
/// Optimization work status update
+ ///
OptimizationStatus,
+ ///
/// Optimization work result
+ ///
OptimizationResult,
+ ///
/// Aggregated packets
+ ///
Aggregated,
+ ///
/// Query the language model
+ ///
LanguageModelQuery,
+ ///
/// Send feedback to a language model response
+ ///
LanguageModelFeedback,
+ ///
/// The language models response
+ ///
LanguageModelResponse,
+ ///
/// Language model code analysis
+ ///
LanguageModelCodeAnalysis,
+ ///
/// Language model chat work
+ ///
LanguageModelChatWork,
+ ///
/// Language model chat response
+ ///
LanguageModelChatResponse,
+ ///
/// Algorithm name update
+ ///
AlgorithmNameUpdate,
+ ///
/// Algorithm tags update
+ ///
AlgorithmTagsUpdate,
+ ///
/// Research job packet
+ ///
ResearchNode,
+ ///
/// Organization update
+ ///
OrganizationUpdate,
+ ///
/// Compiler -> User Build Warnings
+ ///
BuildWarning,
+ ///
/// Language model function call related packet
+ ///
LanguageModelFunctionCall,
+ ///
/// Language model agent message
+ ///
LanguageModelAgentMessage,
}
}
diff --git a/Common/Python/BasePythonWrapper.cs b/Common/Python/BasePythonWrapper.cs
index 956a5ca6b2ea..956c20c90593 100644
--- a/Common/Python/BasePythonWrapper.cs
+++ b/Common/Python/BasePythonWrapper.cs
@@ -15,7 +15,6 @@
using System;
using Python.Runtime;
-using QuantConnect.Util;
using System.Collections.Generic;
namespace QuantConnect.Python
@@ -30,7 +29,7 @@ public class BasePythonWrapper : IEquatable _pythonMethods;
private Dictionary _pythonPropertyNames;
- private readonly bool _validateInterface;
+ private bool _validateInterface;
///
/// Gets the underlying python instance
@@ -43,8 +42,6 @@ public class BasePythonWrapper : IEquatableWhether to perform validations for interface implementation
public BasePythonWrapper(bool validateInterface = true)
{
- _pythonMethods = new();
- _pythonPropertyNames = new();
_validateInterface = validateInterface;
}
@@ -65,14 +62,34 @@ public BasePythonWrapper(PyObject instance, bool validateInterface = true)
/// The underlying python instance
public void SetPythonInstance(PyObject instance)
{
- if (_instance != null)
+ InitializeContainers();
+
+ _instance = _validateInterface ? instance.ValidateImplementationOf() : instance;
+ _instance.TryConvert(out _underlyingClrObject);
+ }
+
+ ///
+ /// Sets the python instance and sets the validate interface flag
+ ///
+ /// The underlying python instance
+ /// Whether to perform validations for interface implementation
+ protected void SetPythonInstance(PyObject instance, bool validateInterface)
+ {
+ _validateInterface = validateInterface;
+ SetPythonInstance(instance);
+ }
+
+ private void InitializeContainers()
+ {
+ if (_pythonMethods != null && _pythonPropertyNames != null)
{
_pythonMethods.Clear();
_pythonPropertyNames.Clear();
+ return;
}
- _instance = _validateInterface ? instance.ValidateImplementationOf() : instance;
- _instance.TryConvert(out _underlyingClrObject);
+ _pythonMethods = new();
+ _pythonPropertyNames = new();
}
///
@@ -131,12 +148,13 @@ public bool HasAttr(string name)
/// Gets the Python instances method with the specified name and caches it
///
/// The name of the method
+ /// Whether to only return python methods
/// The matched method
- public PyObject GetMethod(string methodName)
+ public PyObject GetMethod(string methodName, bool pythonOnly = false)
{
if (!_pythonMethods.TryGetValue(methodName, out var method))
{
- method = _instance.GetMethod(methodName);
+ method = pythonOnly ? _instance.GetPythonMethod(methodName) : _instance.GetMethod(methodName);
_pythonMethods = AddToDictionary(_pythonMethods, methodName, method);
}
@@ -331,6 +349,7 @@ private bool Equals(PyObject other)
return PythonReferenceComparer.Instance.Equals(_instance, other);
}
+
///
/// Dispose of this instance
///
@@ -348,6 +367,31 @@ public virtual void Dispose()
_instance?.Dispose();
}
+ ///
+ /// Attempts to invoke the method if it has been overridden in Python.
+ ///
+ /// The expected return type of the Python method.
+ /// The name of the method to call on the Python instance.
+ /// When this method returns, contains the method result if the call succeeded.
+ /// The arguments to pass to the Python method.
+ /// true if the Python method was successfully invoked, otherwise, false.
+ protected bool TryInvokePythonOverride(string methodName, out T result, params object[] args)
+ {
+
+ if (_instance != null)
+ {
+ var method = GetMethod(methodName, true);
+ if (method != null)
+ {
+ result = PythonRuntimeChecker.InvokeMethod(method, methodName, args);
+ return true;
+ }
+ }
+
+ result = default;
+ return false;
+ }
+
///
/// Set of helper methods to invoke Python methods with runtime checks for return values and out parameter's conversions.
///
diff --git a/Common/Python/DividendYieldModelPythonWrapper.cs b/Common/Python/DividendYieldModelPythonWrapper.cs
index 513058857ee6..25a300392ff4 100644
--- a/Common/Python/DividendYieldModelPythonWrapper.cs
+++ b/Common/Python/DividendYieldModelPythonWrapper.cs
@@ -16,6 +16,7 @@
using System;
using Python.Runtime;
using QuantConnect.Data;
+using QuantConnect.Util;
namespace QuantConnect.Python
{
@@ -62,11 +63,10 @@ public decimal GetDividendYield(DateTime date, decimal securityPrice)
/// The converted instance
public static IDividendYieldModel FromPyObject(PyObject model)
{
- if (!model.TryConvert(out IDividendYieldModel dividendYieldModel))
- {
- dividendYieldModel = new DividendYieldModelPythonWrapper(model);
- }
-
+ var dividendYieldModel = PythonUtil.CreateInstanceOrWrapper(
+ model,
+ py => new DividendYieldModelPythonWrapper(py)
+ );
return dividendYieldModel;
}
}
diff --git a/Common/Python/RiskFreeInterestRateModelPythonWrapper.cs b/Common/Python/RiskFreeInterestRateModelPythonWrapper.cs
index 1eb58a97fa3a..f104007ca255 100644
--- a/Common/Python/RiskFreeInterestRateModelPythonWrapper.cs
+++ b/Common/Python/RiskFreeInterestRateModelPythonWrapper.cs
@@ -16,6 +16,7 @@
using System;
using Python.Runtime;
using QuantConnect.Data;
+using QuantConnect.Util;
namespace QuantConnect.Python
{
@@ -50,11 +51,10 @@ public decimal GetInterestRate(DateTime date)
/// The converted instance
public static IRiskFreeInterestRateModel FromPyObject(PyObject model)
{
- if (!model.TryConvert(out IRiskFreeInterestRateModel riskFreeInterestRateModel))
- {
- riskFreeInterestRateModel = new RiskFreeInterestRateModelPythonWrapper(model);
- }
-
+ var riskFreeInterestRateModel = PythonUtil.CreateInstanceOrWrapper(
+ model,
+ py => new RiskFreeInterestRateModelPythonWrapper(py)
+ );
return riskFreeInterestRateModel;
}
}
diff --git a/Common/QuantConnect.csproj b/Common/QuantConnect.csproj
index 9fa973efd104..e39b3a918c5f 100644
--- a/Common/QuantConnect.csproj
+++ b/Common/QuantConnect.csproj
@@ -2,7 +2,7 @@
Debug
AnyCPU
- net9.0
+ net10.0
QuantConnect.Common
..\
true
@@ -35,7 +35,7 @@
-
+
diff --git a/Common/Result.cs b/Common/Result.cs
index 932a571c257c..13f040b83ad6 100644
--- a/Common/Result.cs
+++ b/Common/Result.cs
@@ -13,10 +13,11 @@
* limitations under the License.
*/
-using System;
using Newtonsoft.Json;
using QuantConnect.Orders;
using QuantConnect.Packets;
+using QuantConnect.Statistics;
+using System;
using System.Collections.Generic;
namespace QuantConnect
@@ -83,6 +84,12 @@ public class Result
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public AlgorithmConfiguration AlgorithmConfiguration { get; set; }
+ ///
+ /// Rolling window detailed statistics.
+ ///
+ [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
+ public AlgorithmPerformance TotalPerformance { get; set; }
+
///
/// Creates new empty instance
///
@@ -103,6 +110,7 @@ public Result(BaseResultParameters parameters)
OrderEvents = parameters.OrderEvents;
AlgorithmConfiguration = parameters.AlgorithmConfiguration;
State = parameters.State;
+ TotalPerformance = parameters.TotalPerformance;
}
}
}
diff --git a/Common/Securities/Cash.cs b/Common/Securities/Cash.cs
index 6858ab484c9e..0c317ab21814 100644
--- a/Common/Securities/Cash.cs
+++ b/Common/Securities/Cash.cs
@@ -262,6 +262,14 @@ public List EnsureCurrencyDataFeed(SecurityManager secur
var cfdEntries = GetAvailableSymbolPropertiesDatabaseEntries(SecurityType.Cfd, marketMap, markets);
var cryptoEntries = GetAvailableSymbolPropertiesDatabaseEntries(SecurityType.Crypto, marketMap, markets);
+ if (marketMap.TryGetValue(SecurityType.CryptoFuture, out var cryptoFutureMarket) && cryptoFutureMarket == Market.DYDX)
+ {
+ // Put additional logic for dYdX crypto futures as they don't have Crypto (Spot) market
+ // Also need to add them first to give the priority
+ // TODO: remove once dydx SPOT market will be imlemented
+ cryptoEntries = GetAvailableSymbolPropertiesDatabaseEntries(SecurityType.CryptoFuture, marketMap, markets).Concat(cryptoEntries);
+ }
+
var potentialEntries = forexEntries
.Concat(cfdEntries)
.Concat(cryptoEntries)
@@ -316,7 +324,9 @@ public List EnsureCurrencyDataFeed(SecurityManager secur
var newSecurity = securityService.CreateSecurity(symbol,
config,
- addToSymbolCache: false);
+ addToSymbolCache: false,
+ // All securities added for currency conversion will be seeded in batch after all are created
+ seedSecurity: false);
Log.Trace("Cash.EnsureCurrencyDataFeed(): " + Messages.Cash.AddingSecuritySymbolForCashCurrencyFeed(symbol, Symbol));
diff --git a/Common/Securities/ContractSecurityFilterUniverse.cs b/Common/Securities/ContractSecurityFilterUniverse.cs
index 2aed39f428b8..7611150f0d7f 100644
--- a/Common/Securities/ContractSecurityFilterUniverse.cs
+++ b/Common/Securities/ContractSecurityFilterUniverse.cs
@@ -27,8 +27,8 @@ namespace QuantConnect.Securities
/// Used by OptionFilterUniverse and FutureFilterUniverse
///
public abstract class ContractSecurityFilterUniverse : IDerivativeSecurityFilterUniverse
- where T: ContractSecurityFilterUniverse
- where TData: IChainUniverseData
+ where T : ContractSecurityFilterUniverse
+ where TData : IChainUniverseData
{
private bool _alreadyAppliedTypeFilters;
@@ -51,11 +51,16 @@ protected enum ContractExpirationType : int
Weekly = 2
}
+ ///
+ /// The default expiration type filter value
+ ///
+ protected static readonly ContractExpirationType DefaultExpirationType = ContractExpirationType.Standard | ContractExpirationType.Weekly;
+
///
/// Expiration Types allowed through the filter
/// Standards only by default
///
- protected ContractExpirationType Type { get; set; } = ContractExpirationType.Standard;
+ protected ContractExpirationType Type { get; set; } = DefaultExpirationType;
///
/// The local exchange current time
@@ -107,6 +112,7 @@ internal IEnumerable AllSymbols
///
protected ContractSecurityFilterUniverse()
{
+ Type = DefaultExpirationType;
}
///
@@ -116,7 +122,7 @@ protected ContractSecurityFilterUniverse(IEnumerable allData, DateTime lo
{
Data = allData;
LocalTime = localTime;
- Type = ContractExpirationType.Standard;
+ Type = DefaultExpirationType;
}
///
@@ -139,7 +145,7 @@ internal T ApplyTypesFilter()
{
if (_alreadyAppliedTypeFilters)
{
- return (T) this;
+ return (T)this;
}
// memoization map for ApplyTypesFilter()
@@ -174,7 +180,7 @@ internal T ApplyTypesFilter()
}).ToList();
_alreadyAppliedTypeFilters = true;
- return (T) this;
+ return (T)this;
}
///
@@ -186,7 +192,7 @@ public virtual void Refresh(IEnumerable allData, DateTime localTime)
{
Data = allData;
LocalTime = localTime;
- Type = ContractExpirationType.Standard;
+ Type = DefaultExpirationType;
_alreadyAppliedTypeFilters = false;
}
@@ -211,6 +217,7 @@ public T StandardsOnly()
/// Includes universe of non-standard weeklys contracts (if any) into selection
///
/// Universe with filter applied
+ [Obsolete("IncludeWeeklys is obsolete because weekly contracts are now included by default.")]
public T IncludeWeeklys()
{
if (_alreadyAppliedTypeFilters)
@@ -241,11 +248,11 @@ public virtual T FrontMonth()
{
ApplyTypesFilter();
var ordered = Data.OrderBy(x => x.ID.Date).ToList();
- if (ordered.Count == 0) return (T) this;
+ if (ordered.Count == 0) return (T)this;
var frontMonth = ordered.TakeWhile(x => ordered[0].ID.Date == x.ID.Date);
Data = frontMonth.ToList();
- return (T) this;
+ return (T)this;
}
///
@@ -256,11 +263,11 @@ public virtual T BackMonths()
{
ApplyTypesFilter();
var ordered = Data.OrderBy(x => x.ID.Date).ToList();
- if (ordered.Count == 0) return (T) this;
+ if (ordered.Count == 0) return (T)this;
var backMonths = ordered.SkipWhile(x => ordered[0].ID.Date == x.ID.Date);
Data = backMonths.ToList();
- return (T) this;
+ return (T)this;
}
///
@@ -351,7 +358,7 @@ public T Contracts(PyObject contracts)
public T Contracts(IEnumerable contracts)
{
AllSymbols = contracts.ToList();
- return (T) this;
+ return (T)this;
}
///
@@ -376,7 +383,7 @@ public T Contracts(Func, IEnumerable> contractSelecto
{
// force materialization using ToList
AllSymbols = contractSelector(Data).ToList();
- return (T) this;
+ return (T)this;
}
///
@@ -400,7 +407,7 @@ public T Contracts(Func, IEnumerable> contractSelector
[Obsolete("Deprecated as of 2023-12-13. Filters are always non-dynamic as of now, which means they will only bee applied daily.")]
public T OnlyApplyFilterAtMarketOpen()
{
- return (T) this;
+ return (T)this;
}
///
diff --git a/Common/Securities/CryptoFuture/dYdXFutureMarginInterestRateModel.cs b/Common/Securities/CryptoFuture/dYdXFutureMarginInterestRateModel.cs
new file mode 100644
index 000000000000..42c7fa2371fa
--- /dev/null
+++ b/Common/Securities/CryptoFuture/dYdXFutureMarginInterestRateModel.cs
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ *
+*/
+
+namespace QuantConnect.Securities.CryptoFuture
+{
+ ///
+ /// The responsibility of this model is to apply future funding rate cash flows to the portfolio based on open positions
+ ///
+ public class dYdXFutureMarginInterestRateModel : BinanceFutureMarginInterestRateModel
+ {
+ }
+}
diff --git a/Common/Securities/Future/FuturesExpiryFunctions.cs b/Common/Securities/Future/FuturesExpiryFunctions.cs
index 56946b03e0da..c0cbc9fe9d74 100644
--- a/Common/Securities/Future/FuturesExpiryFunctions.cs
+++ b/Common/Securities/Future/FuturesExpiryFunctions.cs
@@ -158,7 +158,7 @@ public static Func FuturesExpiryFunction(Symbol symbol)
}
// Trading can occur up to 9:30 a.m. Eastern Time (ET) on the 3rd Friday of the contract month
- var thirdFriday = FuturesExpiryUtilityFunctions.ThirdFriday(time);
+ var thirdFriday = FuturesExpiryUtilityFunctions.ThirdFriday(time, Symbol.Create(Futures.Indices.SP500EMini, SecurityType.Future, Market.CME));
return thirdFriday.Add(new TimeSpan(13,30,0));
})
},
@@ -217,7 +217,7 @@ public static Func FuturesExpiryFunction(Symbol symbol)
}
// Trading can occur up to 9:30 a.m. Eastern Time (ET) on the 3rd Friday of the contract month
- var thirdFriday = FuturesExpiryUtilityFunctions.ThirdFriday(time);
+ var thirdFriday = FuturesExpiryUtilityFunctions.ThirdFriday(time, Symbol.Create(Futures.Indices.NASDAQ100EMini, SecurityType.Future, Market.CME));
return thirdFriday.Add(new TimeSpan(13,30,0));
})
},
@@ -231,7 +231,7 @@ public static Func FuturesExpiryFunction(Symbol symbol)
}
// Trading can occur up to 9:30 a.m. Eastern Time (ET) on the 3rd Friday of the contract month
- var thirdFriday = FuturesExpiryUtilityFunctions.ThirdFriday(time);
+ var thirdFriday = FuturesExpiryUtilityFunctions.ThirdFriday(time, Symbol.Create(Futures.Indices.Dow30EMini, SecurityType.Future, Market.CBOT));
return thirdFriday.Add(new TimeSpan(13,30,0));
})
},
@@ -245,7 +245,7 @@ public static Func FuturesExpiryFunction(Symbol symbol)
}
// Trading can occur up to 9:30 a.m. Eastern Time (ET) on the 3rd Friday of the contract month
- var thirdFriday = FuturesExpiryUtilityFunctions.ThirdFriday(time);
+ var thirdFriday = FuturesExpiryUtilityFunctions.ThirdFriday(time, Symbol.Create(Futures.Indices.Russell2000EMini, SecurityType.Future, Market.CME));
return thirdFriday.Add(new TimeSpan (13,30,0));
})
},
@@ -3208,7 +3208,7 @@ Dec listed in June
}
// Trading terminates at 9:30 a.m. ET on the 3rd Friday of the contract month.
- var thirdFriday = FuturesExpiryUtilityFunctions.ThirdFriday(time);
+ var thirdFriday = FuturesExpiryUtilityFunctions.ThirdFriday(time, Symbol.Create(Futures.Indices.MicroSP500EMini, SecurityType.Future, Market.CME));
return thirdFriday.Add(new TimeSpan(13,30,0));
})
},
@@ -3222,7 +3222,7 @@ Dec listed in June
}
// Trading terminates at 9:30 a.m. ET on the 3rd Friday of the contract month.
- var thirdFriday = FuturesExpiryUtilityFunctions.ThirdFriday(time);
+ var thirdFriday = FuturesExpiryUtilityFunctions.ThirdFriday(time, Symbol.Create(Futures.Indices.MicroNASDAQ100EMini, SecurityType.Future, Market.CME));
return thirdFriday.Add(new TimeSpan(13,30,0));
})
},
@@ -3236,7 +3236,7 @@ Dec listed in June
}
// Trading terminates at 9:30 a.m. ET on the 3rd Friday of the contract month.
- var thirdFriday = FuturesExpiryUtilityFunctions.ThirdFriday(time);
+ var thirdFriday = FuturesExpiryUtilityFunctions.ThirdFriday(time, Symbol.Create(Futures.Indices.MicroRussell2000EMini, SecurityType.Future, Market.CME));
return thirdFriday.Add(new TimeSpan(13,30,0));
})
},
@@ -3250,7 +3250,7 @@ Dec listed in June
}
// Trading can occur up to 9:30 a.m. Eastern Time (ET) on the 3rd Friday of the contract month
- var thirdFriday = FuturesExpiryUtilityFunctions.ThirdFriday(time);
+ var thirdFriday = FuturesExpiryUtilityFunctions.ThirdFriday(time, Symbol.Create(Futures.Indices.MicroDow30EMini, SecurityType.Future, Market.CBOT));
return thirdFriday.Add(new TimeSpan(13,30,0));
})
},
diff --git a/Common/Securities/Future/FuturesListings.cs b/Common/Securities/Future/FuturesListings.cs
index 3e3a9007309b..dad4e6d430a5 100644
--- a/Common/Securities/Future/FuturesListings.cs
+++ b/Common/Securities/Future/FuturesListings.cs
@@ -36,6 +36,12 @@ public static class FuturesListings
private static readonly Symbol _zl = Symbol.Create("ZL", SecurityType.Future, Market.CBOT);
private static readonly Symbol _zw = Symbol.Create("ZW", SecurityType.Future, Market.CBOT);
private static readonly Symbol _tn = Symbol.Create("TN", SecurityType.Future, Market.CBOT);
+ private static readonly Symbol _aud = Symbol.Create("6A", SecurityType.Future, Market.CME);
+ private static readonly Symbol _gbp = Symbol.Create("6B", SecurityType.Future, Market.CME);
+ private static readonly Symbol _mxn = Symbol.Create("6M", SecurityType.Future, Market.CME);
+ private static readonly Symbol _jpy = Symbol.Create("6J", SecurityType.Future, Market.CME);
+ private static readonly Symbol _eur = Symbol.Create("6E", SecurityType.Future, Market.CME);
+ private static readonly Symbol _cad = Symbol.Create("6C", SecurityType.Future, Market.CME);
private static Dictionary>> _futuresListingRules = new Dictionary>>
{
@@ -71,7 +77,13 @@ public static class FuturesListings
_zw,
t,
7,
- new FuturesListingCycles(new[] { 3, 5, 7, 9, 12 }, 15)) }
+ new FuturesListingCycles(new[] { 3, 5, 7, 9, 12 }, 15)) },
+ { "6A", t => QuarterlyContracts(_aud, t, 8) },
+ { "6B", t => QuarterlyContracts(_gbp, t, 8) },
+ { "6M", t => QuarterlyContracts(_mxn, t, 8) },
+ { "6J", t => QuarterlyContracts(_jpy, t, 8) },
+ { "6E", t => QuarterlyContracts(_eur, t, 8) },
+ { "6C", t => QuarterlyContracts(_cad, t, 8) },
};
///
diff --git a/Common/Securities/FutureOption/FuturesOptionsExpiryFunctions.cs b/Common/Securities/FutureOption/FuturesOptionsExpiryFunctions.cs
index e46ebea1c952..a6695fdb0a7a 100644
--- a/Common/Securities/FutureOption/FuturesOptionsExpiryFunctions.cs
+++ b/Common/Securities/FutureOption/FuturesOptionsExpiryFunctions.cs
@@ -50,6 +50,7 @@ public static class FuturesOptionsExpiryFunctions
private static readonly Symbol _jpu = Symbol.CreateCanonicalOption(Symbol.Create("6J", SecurityType.Future, Market.CME));
private static readonly Symbol _chu = Symbol.CreateCanonicalOption(Symbol.Create("6S", SecurityType.Future, Market.CME));
private static readonly Symbol _nzd = Symbol.CreateCanonicalOption(Symbol.Create("6N", SecurityType.Future, Market.CME));
+ private static readonly Symbol _mxn = Symbol.CreateCanonicalOption(Symbol.Create("6M", SecurityType.Future, Market.CME));
private static readonly Symbol _le = Symbol.CreateCanonicalOption(Symbol.Create("LE", SecurityType.Future, Market.CME));
private static readonly Symbol _he = Symbol.CreateCanonicalOption(Symbol.Create("HE", SecurityType.Future, Market.CME));
private static readonly Symbol _lbr = Symbol.CreateCanonicalOption(Symbol.Create("LBR", SecurityType.Future, Market.CME));
@@ -97,6 +98,7 @@ public static class FuturesOptionsExpiryFunctions
{ _jpu, expiryMonth => SecondFridayBeforeThirdWednesdayOfContractMonth(_jpu.Underlying, expiryMonth) },
{ _chu, expiryMonth => SecondFridayBeforeThirdWednesdayOfContractMonth(_chu.Underlying, expiryMonth) },
{ _nzd, expiryMonth => SecondFridayBeforeThirdWednesdayOfContractMonth(_nzd.Underlying, expiryMonth) },
+ { _mxn, expiryMonth => SecondFridayBeforeThirdWednesdayOfContractMonth(_mxn.Underlying, expiryMonth) },
{ _le, expiryMonth => FirstFridayOfContractMonth(_le.Underlying, expiryMonth) },
{ _he, expiryMonth => TenthBusinessDayOfContractMonth(_he.Underlying, expiryMonth) },
{ _lbr, expiryMonth => LastBusinessDayInPrecedingMonthFromContractMonth(_lbr.Underlying, expiryMonth) },
diff --git a/Common/Securities/FutureOption/FuturesOptionsUnderlyingMapper.cs b/Common/Securities/FutureOption/FuturesOptionsUnderlyingMapper.cs
index 3aa254e63b38..17ef2ba373af 100644
--- a/Common/Securities/FutureOption/FuturesOptionsUnderlyingMapper.cs
+++ b/Common/Securities/FutureOption/FuturesOptionsUnderlyingMapper.cs
@@ -60,7 +60,15 @@ public static class FuturesOptionsUnderlyingMapper
// COMEX
{ "HG", (d, _) => ContractMonthYearStartThreeMonthsThenEvenOddMonthsSkipRule(d, true) },
{ "SI", (d, _) => ContractMonthYearStartThreeMonthsThenEvenOddMonthsSkipRule(d, true) },
- { "GC", (d, _) => ContractMonthEvenOddMonth(d, false) }
+ { "GC", (d, _) => ContractMonthEvenOddMonth(d, false) },
+
+ // CME
+ { "6A", (d, ld) => ContractMonthSerialLookupRule(Symbol.Create("6A", SecurityType.Future, Market.CME), d, ld.Value) },
+ { "6B", (d, ld) => ContractMonthSerialLookupRule(Symbol.Create("6B", SecurityType.Future, Market.CME), d, ld.Value) },
+ { "6M", (d, ld) => ContractMonthSerialLookupRule(Symbol.Create("6M", SecurityType.Future, Market.CME), d, ld.Value) },
+ { "6J", (d, ld) => ContractMonthSerialLookupRule(Symbol.Create("6J", SecurityType.Future, Market.CME), d, ld.Value) },
+ { "6E", (d, ld) => ContractMonthSerialLookupRule(Symbol.Create("6E", SecurityType.Future, Market.CME), d, ld.Value) },
+ { "6C", (d, ld) => ContractMonthSerialLookupRule(Symbol.Create("6C", SecurityType.Future, Market.CME), d, ld.Value) },
};
///
diff --git a/Common/Securities/Interfaces/IContinuousContractModel.cs b/Common/Securities/Interfaces/IContinuousContractModel.cs
index 1af3560d3166..d3d257c73cf7 100644
--- a/Common/Securities/Interfaces/IContinuousContractModel.cs
+++ b/Common/Securities/Interfaces/IContinuousContractModel.cs
@@ -24,10 +24,14 @@ namespace QuantConnect.Securities.Interfaces
///
public enum AdjustmentType
{
+ ///
/// ForwardAdjusted - new quotes are adjusted as new data comes
+ ///
ForwardAdjusted,
+ ///
/// BackAdjusted - old quotes are retrospectively adjusted as new data comes
+ ///
BackAdjusted
};
diff --git a/Common/Securities/Option/Option.cs b/Common/Securities/Option/Option.cs
index eee3861b74e8..75b74b13d828 100644
--- a/Common/Securities/Option/Option.cs
+++ b/Common/Securities/Option/Option.cs
@@ -45,7 +45,7 @@ public class Option : Security, IDerivativeSecurity, IOptionPrice
///
/// The default time of day for settlement
///
- public static readonly TimeSpan DefaultSettlementTime = new (6, 0, 0);
+ public static readonly TimeSpan DefaultSettlementTime = new(6, 0, 0);
///
/// Constructor for the option security
@@ -443,7 +443,7 @@ public bool EnableGreekApproximation
var model = PriceModel as QLOptionPriceModel;
if (model != null)
{
- model.EnableGreekApproximation = value;
+ model.EnableGreekApproximation = value;
}
}
}
@@ -462,22 +462,10 @@ public IDerivativeSecurityFilter ContractFilter
/// The option assignment model to use
public void SetOptionAssignmentModel(PyObject pyObject)
{
- if (pyObject.TryConvert(out var optionAssignmentModel))
- {
- // pure C# implementation
- SetOptionAssignmentModel(optionAssignmentModel);
- }
- else if (Extensions.TryConvert(pyObject, out _, allowPythonDerivative: true))
- {
- SetOptionAssignmentModel(new OptionAssignmentModelPythonWrapper(pyObject));
- }
- else
- {
- using(Py.GIL())
- {
- throw new ArgumentException($"SetOptionAssignmentModel: {pyObject.Repr()} is not a valid argument.");
- }
- }
+ OptionAssignmentModel = PythonUtil.CreateInstanceOrWrapper(
+ pyObject,
+ py => new OptionAssignmentModelPythonWrapper(py)
+ );
}
///
@@ -495,22 +483,10 @@ public void SetOptionAssignmentModel(IOptionAssignmentModel optionAssignmentMode
/// The option exercise model to use
public void SetOptionExerciseModel(PyObject pyObject)
{
- if (pyObject.TryConvert(out var optionExerciseModel))
- {
- // pure C# implementation
- SetOptionExerciseModel(optionExerciseModel);
- }
- else if (Extensions.TryConvert(pyObject, out _, allowPythonDerivative: true))
- {
- SetOptionExerciseModel(new OptionExerciseModelPythonWrapper(pyObject));
- }
- else
- {
- using (Py.GIL())
- {
- throw new ArgumentException($"SetOptionExerciseModel: {pyObject.Repr()} is not a valid argument.");
- }
- }
+ OptionExerciseModel = PythonUtil.CreateInstanceOrWrapper(
+ pyObject,
+ py => new OptionExerciseModelPythonWrapper(py)
+ );
}
///
diff --git a/Common/Securities/Option/OptionFilterUniverse.cs b/Common/Securities/Option/OptionFilterUniverse.cs
index 350a544a5ceb..7f193be0342c 100644
--- a/Common/Securities/Option/OptionFilterUniverse.cs
+++ b/Common/Securities/Option/OptionFilterUniverse.cs
@@ -58,6 +58,7 @@ public BaseData Underlying
///
/// Constructs OptionFilterUniverse
+ /// By default, the filter includes both standard and weekly contracts.
///
/// The canonical option chain security
public OptionFilterUniverse(Option.Option option)
diff --git a/Common/Securities/Security.cs b/Common/Securities/Security.cs
index 67e4e7a3406b..b3a2106dc692 100644
--- a/Common/Securities/Security.cs
+++ b/Common/Securities/Security.cs
@@ -33,6 +33,7 @@
using QuantConnect.Data.Fundamental;
using QuantConnect.Interfaces;
using QuantConnect.Data.Shortable;
+using QuantConnect.Util;
namespace QuantConnect.Securities
{
@@ -725,7 +726,10 @@ public void SetFeeModel(IFeeModel feelModel)
/// Model that represents a fee model
public void SetFeeModel(PyObject feelModel)
{
- FeeModel = new FeeModelPythonWrapper(feelModel);
+ FeeModel = PythonUtil.CreateInstanceOrWrapper(
+ feelModel,
+ py => new FeeModelPythonWrapper(py)
+ );
}
///
@@ -743,7 +747,10 @@ public void SetFillModel(IFillModel fillModel)
/// Model that represents a fill model
public void SetFillModel(PyObject fillModel)
{
- FillModel = new FillModelPythonWrapper(fillModel);
+ FillModel = PythonUtil.CreateInstanceOrWrapper(
+ fillModel,
+ py => new FillModelPythonWrapper(py)
+ );
}
///
@@ -761,7 +768,10 @@ public void SetSettlementModel(ISettlementModel settlementModel)
/// Model that represents a settlement model
public void SetSettlementModel(PyObject settlementModel)
{
- SettlementModel = new SettlementModelPythonWrapper(settlementModel);
+ SettlementModel = PythonUtil.CreateInstanceOrWrapper(
+ settlementModel,
+ py => new SettlementModelPythonWrapper(py)
+ );
}
///
@@ -779,7 +789,10 @@ public void SetSlippageModel(ISlippageModel slippageModel)
/// Model that represents a slippage model
public void SetSlippageModel(PyObject slippageModel)
{
- SlippageModel = new SlippageModelPythonWrapper(slippageModel);
+ SlippageModel = PythonUtil.CreateInstanceOrWrapper(
+ slippageModel,
+ py => new SlippageModelPythonWrapper(py)
+ );
}
///
@@ -797,7 +810,10 @@ public void SetVolatilityModel(IVolatilityModel volatilityModel)
/// Model that represents a volatility model
public void SetVolatilityModel(PyObject volatilityModel)
{
- VolatilityModel = new VolatilityModelPythonWrapper(volatilityModel);
+ VolatilityModel = PythonUtil.CreateInstanceOrWrapper(
+ volatilityModel,
+ py => new VolatilityModelPythonWrapper(py)
+ );
}
///
@@ -815,7 +831,10 @@ public void SetBuyingPowerModel(IBuyingPowerModel buyingPowerModel)
/// Model that represents a security's model of buying power
public void SetBuyingPowerModel(PyObject pyObject)
{
- SetBuyingPowerModel(new BuyingPowerModelPythonWrapper(pyObject));
+ BuyingPowerModel = PythonUtil.CreateInstanceOrWrapper(
+ pyObject,
+ py => new BuyingPowerModelPythonWrapper(py)
+ );
}
///
@@ -833,7 +852,10 @@ public void SetMarginInterestRateModel(IMarginInterestRateModel marginInterestRa
/// Model that represents a security's model of margin interest rate
public void SetMarginInterestRateModel(PyObject pyObject)
{
- SetMarginInterestRateModel(new MarginInterestRateModelPythonWrapper(pyObject));
+ MarginInterestRateModel = PythonUtil.CreateInstanceOrWrapper(
+ pyObject,
+ py => new MarginInterestRateModelPythonWrapper(py)
+ );
}
///
@@ -851,7 +873,10 @@ public void SetMarginModel(IBuyingPowerModel marginModel)
/// Model that represents a security's model of buying power
public void SetMarginModel(PyObject pyObject)
{
- SetMarginModel(new BuyingPowerModelPythonWrapper(pyObject));
+ MarginModel = PythonUtil.CreateInstanceOrWrapper(
+ pyObject,
+ py => new BuyingPowerModelPythonWrapper(py)
+ );
}
///
@@ -860,21 +885,10 @@ public void SetMarginModel(PyObject pyObject)
/// Python class that represents a custom shortable provider
public void SetShortableProvider(PyObject pyObject)
{
- if (pyObject.TryConvert(out var shortableProvider))
- {
- SetShortableProvider(shortableProvider);
- }
- else if (Extensions.TryConvert(pyObject, out _, allowPythonDerivative: true))
- {
- SetShortableProvider(new ShortableProviderPythonWrapper(pyObject));
- }
- else
- {
- using (Py.GIL())
- {
- throw new Exception($"SetShortableProvider: {pyObject.Repr()} is not a valid argument");
- }
- }
+ ShortableProvider = PythonUtil.CreateInstanceOrWrapper(
+ pyObject,
+ py => new ShortableProviderPythonWrapper(py)
+ );
}
///
@@ -893,21 +907,10 @@ public void SetShortableProvider(IShortableProvider shortableProvider)
///
public void SetDataFilter(PyObject pyObject)
{
- if (pyObject.TryConvert(out var dataFilter))
- {
- SetDataFilter(dataFilter);
- }
- else if (Extensions.TryConvert(pyObject, out _, allowPythonDerivative: true))
- {
- SetDataFilter(new SecurityDataFilterPythonWrapper(pyObject));
- }
- else
- {
- using (Py.GIL())
- {
- throw new ArgumentException($"SetDataFilter: {pyObject.Repr()} is not a valid argument");
- }
- }
+ DataFilter = PythonUtil.CreateInstanceOrWrapper(
+ pyObject,
+ py => new SecurityDataFilterPythonWrapper(py)
+ );
}
///
diff --git a/Common/Securities/SecurityCache.cs b/Common/Securities/SecurityCache.cs
index fb8a61df68c8..bdad5adbae61 100644
--- a/Common/Securities/SecurityCache.cs
+++ b/Common/Securities/SecurityCache.cs
@@ -165,9 +165,10 @@ public void AddDataList(IReadOnlyList data, Type dataType, bool? conta
}
}
- var last = data[data.Count - 1];
-
- ProcessDataPoint(last, cacheByType: false);
+ for (var i = 0; i < data.Count; i++)
+ {
+ ProcessDataPoint(data[i], cacheByType: false);
+ }
}
///
diff --git a/Common/Securities/SecurityService.cs b/Common/Securities/SecurityService.cs
index 9ba4d2a80fa0..1cfd4e77cc7a 100644
--- a/Common/Securities/SecurityService.cs
+++ b/Common/Securities/SecurityService.cs
@@ -73,10 +73,14 @@ private Security CreateSecurity(Symbol symbol,
bool addToSymbolCache,
Security underlying,
bool initializeSecurity,
- bool reCreateSecurity)
+ bool reCreateSecurity,
+ bool seedSecurity)
{
var configList = new SubscriptionDataConfigList(symbol);
- configList.AddRange(subscriptionDataConfigList);
+ if (subscriptionDataConfigList != null)
+ {
+ configList.AddRange(subscriptionDataConfigList);
+ }
if (!reCreateSecurity && _algorithm != null && _algorithm.Securities.TryGetValue(symbol, out var existingSecurity))
{
@@ -88,7 +92,7 @@ private Security CreateSecurity(Symbol symbol,
existingSecurity.MakeTradable();
}
- InitializeSecurity(initializeSecurity, existingSecurity);
+ InitializeSecurity(initializeSecurity, existingSecurity, seedSecurity);
return existingSecurity;
}
@@ -231,7 +235,7 @@ private Security CreateSecurity(Symbol symbol,
security.AddData(configList);
// invoke the security initializer
- InitializeSecurity(initializeSecurity, security);
+ InitializeSecurity(initializeSecurity, security, seedSecurity);
CheckCanonicalSecurityModels(security);
@@ -262,10 +266,11 @@ public Security CreateSecurity(Symbol symbol,
List subscriptionDataConfigList,
decimal leverage = 0,
bool addToSymbolCache = true,
- Security underlying = null)
+ Security underlying = null,
+ bool seedSecurity = true)
{
return CreateSecurity(symbol, subscriptionDataConfigList, leverage, addToSymbolCache, underlying,
- initializeSecurity: true, reCreateSecurity: false);
+ initializeSecurity: true, reCreateSecurity: false, seedSecurity: seedSecurity);
}
///
@@ -273,9 +278,14 @@ public Security CreateSecurity(Symbol symbol,
///
/// Following the obsoletion of Security.Subscriptions,
/// both overloads will be merged removing arguments
- public Security CreateSecurity(Symbol symbol, SubscriptionDataConfig subscriptionDataConfig, decimal leverage = 0, bool addToSymbolCache = true, Security underlying = null)
+ public Security CreateSecurity(Symbol symbol,
+ SubscriptionDataConfig subscriptionDataConfig,
+ decimal leverage = 0,
+ bool addToSymbolCache = true,
+ Security underlying = null,
+ bool seedSecurity = true)
{
- return CreateSecurity(symbol, new List { subscriptionDataConfig }, leverage, addToSymbolCache, underlying);
+ return CreateSecurity(symbol, new List { subscriptionDataConfig }, leverage, addToSymbolCache, underlying, seedSecurity);
}
///
@@ -291,7 +301,8 @@ public Security CreateBenchmarkSecurity(Symbol symbol)
addToSymbolCache: false,
underlying: null,
initializeSecurity: false,
- reCreateSecurity: true);
+ reCreateSecurity: true,
+ seedSecurity: false);
}
///
@@ -328,10 +339,15 @@ private void CheckCanonicalSecurityModels(Security security)
}
}
- private void InitializeSecurity(bool initializeSecurity, Security security)
+ private void InitializeSecurity(bool initializeSecurity, Security security, bool seedSecurity)
{
if (initializeSecurity && !security.IsInitialized)
{
+ if (seedSecurity && _algorithm != null && _algorithm.Settings.SeedInitialPrices)
+ {
+ AlgorithmUtils.SeedSecurities([security], _algorithm);
+ }
+
_securityInitializerProvider.SecurityInitializer.Initialize(security);
security.IsInitialized = true;
}
diff --git a/Common/Securities/UniverseManager.cs b/Common/Securities/UniverseManager.cs
index 774f57a12bea..793db584179b 100644
--- a/Common/Securities/UniverseManager.cs
+++ b/Common/Securities/UniverseManager.cs
@@ -21,161 +21,62 @@
using System.Linq;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Util;
+using Common.Util;
namespace QuantConnect.Securities
{
///
/// Manages the algorithm's collection of universes
///
- public class UniverseManager : IDictionary, INotifyCollectionChanged
+ public class UniverseManager : BaseExtendedDictionary>
{
- private readonly Queue _pendingChanges = new();
- private readonly ConcurrentDictionary _universes;
+ private readonly Queue _pendingChanges = new();
///
/// Event fired when a universe is added or removed
///
- public event NotifyCollectionChangedEventHandler CollectionChanged;
+ public event EventHandler CollectionChanged;
///
/// Read-only dictionary containing all active securities. An active security is
/// a security that is currently selected by the universe or has holdings or open orders.
///
- public IReadOnlyDictionary ActiveSecurities => this
+ public ReadOnlyExtendedDictionary ActiveSecurities => this
.SelectMany(ukvp => ukvp.Value.Members.Select(mkvp => mkvp.Value))
- .DistinctBy(s => s.Symbol).ToDictionary(s => s.Symbol);
+ .DistinctBy(s => s.Symbol)
+ .ToReadOnlyExtendedDictionary(s => s.Symbol);
///
/// Initializes a new instance of the class
///
- public UniverseManager()
+ public UniverseManager() : base(new ConcurrentDictionary())
{
- _universes = new ConcurrentDictionary();
- }
-
- #region IDictionary implementation
-
- ///
- /// Returns an enumerator that iterates through the collection.
- ///
- ///
- /// A that can be used to iterate through the collection.
- ///
- /// 1
- public IEnumerator> GetEnumerator()
- {
- return _universes.GetEnumerator();
- }
-
- ///
- /// Returns an enumerator that iterates through a collection.
- ///
- ///
- /// An