Skip to content

Commit 521b81a

Browse files
committed
Improve regression algorithms
1 parent dafad31 commit 521b81a

2 files changed

Lines changed: 106 additions & 0 deletions
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
3+
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
using System;
17+
using System.Collections.Generic;
18+
using QuantConnect.Securities;
19+
20+
namespace QuantConnect.Algorithm.CSharp
21+
{
22+
/// <summary>
23+
/// Regression algorithm testing the behavior of the algorithm when a security is removed and re-added.
24+
/// It asserts that the securities are marked as non-tradable when removed and that they are tradable when re-added.
25+
/// It also asserts that the algorithm receives the correct security changed events for the added and removed securities.
26+
///
27+
/// Additionally, it tests that the security is initialized after every addition, and no more.
28+
///
29+
/// This specific algorithm tests this behavior for manually added future contracts.
30+
/// </summary>
31+
public class SecurityInitializationOnReAdditionForManuallyAddedFutureContractRegressionAlgorithm : SecurityInitializationOnReAdditionForEquityRegressionAlgorithm
32+
{
33+
private static readonly Symbol _futureContractSymbol = QuantConnect.Symbol.CreateFuture(Futures.Indices.SP500EMini, Market.CME, new DateTime(2013, 12, 20));
34+
35+
protected override DateTime StartTimeToUse => new DateTime(2013, 10, 07);
36+
37+
protected override DateTime EndTimeToUse => new DateTime(2013, 10, 17);
38+
39+
protected override Security AddSecurity()
40+
{
41+
return AddFutureContract(_futureContractSymbol, Resolution.Daily);
42+
}
43+
44+
/// <summary>
45+
/// Data Points count of all timeslices of algorithm
46+
/// </summary>
47+
public override long DataPoints => 85;
48+
49+
/// <summary>
50+
/// Data Points count of the algorithm history
51+
/// </summary>
52+
public override int AlgorithmHistoryDataPoints => 48;
53+
54+
/// <summary>
55+
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
56+
/// </summary>
57+
public override Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
58+
{
59+
{"Total Orders", "0"},
60+
{"Average Win", "0%"},
61+
{"Average Loss", "0%"},
62+
{"Compounding Annual Return", "0%"},
63+
{"Drawdown", "0%"},
64+
{"Expectancy", "0"},
65+
{"Start Equity", "100000"},
66+
{"End Equity", "100000"},
67+
{"Net Profit", "0%"},
68+
{"Sharpe Ratio", "0"},
69+
{"Sortino Ratio", "0"},
70+
{"Probabilistic Sharpe Ratio", "0%"},
71+
{"Loss Rate", "0%"},
72+
{"Win Rate", "0%"},
73+
{"Profit-Loss Ratio", "0"},
74+
{"Alpha", "0"},
75+
{"Beta", "0"},
76+
{"Annual Standard Deviation", "0"},
77+
{"Annual Variance", "0"},
78+
{"Information Ratio", "-9.029"},
79+
{"Tracking Error", "0.155"},
80+
{"Treynor Ratio", "0"},
81+
{"Total Fees", "$0.00"},
82+
{"Estimated Strategy Capacity", "$0"},
83+
{"Lowest Capacity Asset", ""},
84+
{"Portfolio Turnover", "0%"},
85+
{"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
86+
};
87+
}
88+
}

Algorithm.CSharp/SecurityInitializationOnReAdditionForSelectedOptionRegressionAlgorithm.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ namespace QuantConnect.Algorithm.CSharp
3434
/// </summary>
3535
public class SecurityInitializationOnReAdditionForSelectedOptionRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
3636
{
37+
private Symbol _canonicalOption;
3738
private List<Symbol> _contractsToSelect;
3839
private HashSet<Option> _selectedContracts = new();
3940
private bool _selectSingle;
@@ -93,6 +94,8 @@ public override void Initialize()
9394
Log($"[{Time}] [{UtcTime}] Selecting {string.Join(", ", selected.Select(x => x.Value))}");
9495
return selected;
9596
}));
97+
98+
_canonicalOption = option.Symbol;
9699
}
97100

98101
public override void OnSecuritiesChanged(SecurityChanges changes)
@@ -113,6 +116,21 @@ public override void OnSecuritiesChanged(SecurityChanges changes)
113116
}
114117
}
115118

119+
var underlyingEquity = changes.AddedSecurities.FirstOrDefault(x => x.Symbol == _canonicalOption.Underlying);
120+
if (Time == StartDate)
121+
{
122+
if (underlyingEquity == null)
123+
{
124+
throw new RegressionTestException($"Expected the underlying equity to be added. " +
125+
$"Added: {string.Join(", ", changes.AddedSecurities.Select(x => x.Symbol.Value))}");
126+
}
127+
}
128+
else if (underlyingEquity != null)
129+
{
130+
throw new RegressionTestException($"Expected the underlying equity to not be added. " +
131+
$"Added: {string.Join(", ", changes.AddedSecurities.Select(x => x.Symbol.Value))}");
132+
}
133+
116134
var addedContracts = changes.AddedSecurities.OfType<Option>().ToList();
117135
if (addedContracts.Any(x => !_securityInializationCounts.TryGetValue(x, out var count) || count != 1))
118136
{

0 commit comments

Comments
 (0)