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
+
1
16
using System ;
2
17
using System . Collections . Generic ;
3
18
using System . Linq ;
4
- using QuantConnect . Algorithm . Framework . Portfolio ;
5
- using QuantConnect . Data ;
6
19
using QuantConnect . Interfaces ;
7
20
using QuantConnect . Orders ;
8
21
9
22
namespace QuantConnect . Algorithm . CSharp
10
23
{
24
+ /// <summary>
25
+ /// A regression test algorithm that places market and limit orders, then liquidates all holdings,
26
+ /// ensuring orders are canceled and the portfolio is empty.
27
+ /// </summary>
11
28
public class LiquidateRegressionAlgorithm : QCAlgorithm , IRegressionAlgorithmDefinition
12
29
{
13
30
protected Symbol _spy ;
14
31
protected Symbol _ibm ;
15
32
public override void Initialize ( )
16
33
{
17
- SetStartDate ( 2018 , 1 , 5 ) ;
34
+ SetStartDate ( 2018 , 1 , 4 ) ;
18
35
SetEndDate ( 2018 , 1 , 10 ) ;
19
36
SetCash ( 100000 ) ;
20
37
_spy = AddEquity ( "SPY" , Resolution . Daily ) . Symbol ;
21
38
_ibm = Symbol ( "IBM R735QTJ8XC9X" ) ;
22
- var security = AddSecurity ( _ibm , Resolution . Daily ) ;
39
+ AddSecurity ( _ibm , Resolution . Daily ) ;
23
40
24
41
// Schedule Rebalance method to be called on specific dates
25
42
Schedule . On ( DateRules . On ( 2018 , 1 , 5 ) , TimeRules . Midnight , Rebalance ) ;
@@ -33,9 +50,26 @@ public virtual void Rebalance()
33
50
34
51
// Place a LimitOrder to sell 1 share at a price below the current market price
35
52
LimitOrder ( _ibm , 1 , Securities [ _ibm ] . Price - 5 ) ;
53
+
54
+
55
+
36
56
LimitOrder ( _spy , 1 , Securities [ _spy ] . Price - 5 ) ;
57
+ var spyOrder = Transactions . GetOpenOrders ( _spy ) . FirstOrDefault ( ) ;
58
+ // Ensure there is an open order for SPY
59
+ if ( spyOrder == null )
60
+ {
61
+ throw new RegressionTestException ( "There should be an open order for SPY." ) ;
62
+ }
63
+
64
+ // Liquidate SPY orders and verify cancellation
65
+ SetHoldings ( _spy , 1 , true ) ;
66
+ var spyCancelOrder = Transactions . GetOrderById ( spyOrder . Id ) ;
67
+ if ( spyCancelOrder . Status != OrderStatus . Canceled )
68
+ {
69
+ throw new RegressionTestException ( "The SPY order should be cancelled." ) ;
70
+ }
37
71
38
- // Liquidate all holdings immediately
72
+ // Liquidate all remaining holdings immediately
39
73
PerformLiquidation ( ) ;
40
74
}
41
75
@@ -48,10 +82,10 @@ public override void OnEndOfAlgorithm()
48
82
{
49
83
// Check if there are any orders that should have been canceled
50
84
var orders = Transactions . GetOrders ( ) . ToList ( ) ;
51
- var cnt = orders . Where ( e => e . Status != OrderStatus . Canceled ) . Count ( ) ;
52
- if ( cnt > 0 )
85
+ var nonCanceledOrdersCount = orders . Where ( e => e . Status != OrderStatus . Canceled ) . Count ( ) ;
86
+ if ( nonCanceledOrdersCount > 0 )
53
87
{
54
- throw new RegressionTestException ( $ "There are { cnt } orders that should have been cancelled") ;
88
+ throw new RegressionTestException ( $ "There are { nonCanceledOrdersCount } orders that should have been cancelled") ;
55
89
}
56
90
57
91
// Check if there are any holdings left in the portfolio
@@ -61,7 +95,7 @@ public override void OnEndOfAlgorithm()
61
95
var holdings = kvp . Value ;
62
96
if ( holdings . Quantity != 0 )
63
97
{
64
- throw new RegressionTestException ( "There are holdings in portfolio" ) ;
98
+ throw new RegressionTestException ( $ "There are { holdings . Quantity } holdings of { symbol } in the portfolio") ;
65
99
}
66
100
}
67
101
}
@@ -84,7 +118,7 @@ public override void OnEndOfAlgorithm()
84
118
/// <summary>
85
119
/// Data Points count of all timeslices of algorithm
86
120
/// </summary>
87
- public long DataPoints => 44 ;
121
+ public long DataPoints => 53 ;
88
122
89
123
/// <summary>
90
124
/// Data Points count of the algorithm history
@@ -96,7 +130,7 @@ public override void OnEndOfAlgorithm()
96
130
/// </summary>
97
131
public Dictionary < string , string > ExpectedStatistics => new Dictionary < string , string >
98
132
{
99
- { "Total Orders" , "3 " } ,
133
+ { "Total Orders" , "8 " } ,
100
134
{ "Average Win" , "0%" } ,
101
135
{ "Average Loss" , "0%" } ,
102
136
{ "Compounding Annual Return" , "0%" } ,
@@ -115,14 +149,14 @@ public override void OnEndOfAlgorithm()
115
149
{ "Beta" , "0" } ,
116
150
{ "Annual Standard Deviation" , "0" } ,
117
151
{ "Annual Variance" , "0" } ,
118
- { "Information Ratio" , "-5.634 " } ,
119
- { "Tracking Error" , "0.024 " } ,
152
+ { "Information Ratio" , "-10.398 " } ,
153
+ { "Tracking Error" , "0.045 " } ,
120
154
{ "Treynor Ratio" , "0" } ,
121
155
{ "Total Fees" , "$0.00" } ,
122
156
{ "Estimated Strategy Capacity" , "$0" } ,
123
157
{ "Lowest Capacity Asset" , "" } ,
124
158
{ "Portfolio Turnover" , "0%" } ,
125
- { "OrderListHash" , "3dc667d309559a7df141959a22aef64c " }
159
+ { "OrderListHash" , "f03dec5648d761ca660e0ea51403aa92 " }
126
160
} ;
127
161
}
128
162
}
0 commit comments