forked from QuantConnect/Lean
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathQCAlgorithmFramework.cs
More file actions
232 lines (202 loc) · 8.74 KB
/
Copy pathQCAlgorithmFramework.cs
File metadata and controls
232 lines (202 loc) · 8.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
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.Linq;
using QuantConnect.Algorithm.Framework.Alphas;
using QuantConnect.Algorithm.Framework.Alphas.Analysis;
using QuantConnect.Algorithm.Framework.Alphas.Analysis.Providers;
using QuantConnect.Algorithm.Framework.Execution;
using QuantConnect.Algorithm.Framework.Portfolio;
using QuantConnect.Algorithm.Framework.Risk;
using QuantConnect.Algorithm.Framework.Selection;
using QuantConnect.Data;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Securities;
using QuantConnect.Util;
namespace QuantConnect.Algorithm.Framework
{
/// <summary>
/// Algorithm framework base class that enforces a modular approach to algorithm development
/// </summary>
public partial class QCAlgorithmFramework : QCAlgorithm
{
private readonly ISecurityValuesProvider _securityValuesProvider;
/// <summary>
/// Returns true since algorithms derived from this use the framework
/// </summary>
public override bool IsFrameworkAlgorithm => true;
/// <summary>
/// Gets or sets the portfolio selection model.
/// </summary>
public IPortfolioSelectionModel PortfolioSelection { get; set; }
/// <summary>
/// Gets or sets the alpha model
/// </summary>
public IAlphaModel Alpha { get; set; }
/// <summary>
/// Gets or sets the portoflio construction model
/// </summary>
public IPortfolioConstructionModel PortfolioConstruction { get; set; }
/// <summary>
/// Gets or sets the execution model
/// </summary>
public IExecutionModel Execution { get; set; }
/// <summary>
/// Gets or sets the risk management model
/// </summary>
public IRiskManagementModel RiskManagement { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="QCAlgorithmFramework"/> class
/// </summary>
public QCAlgorithmFramework()
{
_securityValuesProvider = new AlgorithmSecurityValuesProvider(this);
// set model defaults
Execution = new ImmediateExecutionModel();
RiskManagement = new NullRiskManagementModel();
}
/// <summary>
/// Called by setup handlers after Initialize and allows the algorithm a chance to organize
/// the data gather in the Initialize method
/// </summary>
public override void PostInitialize()
{
CheckModels();
foreach (var universe in PortfolioSelection.CreateUniverses(this))
{
AddUniverse(universe);
}
base.PostInitialize();
}
/// <summary>
/// Used to send data updates to algorithm framework models
/// </summary>
/// <param name="slice">The current data slice</param>
public sealed override void OnFrameworkData(Slice slice)
{
// generate, timestamp and emit insights
var insights = Alpha.Update(this, slice)
.Select(SetGeneratedAndClosedTimes)
.ToList();
if (insights.Count != 0)
{
// only fire insights generated event if we actually have insights
OnInsightsGenerated(insights);
}
// construct portfolio targets from insights
var targets = PortfolioConstruction.CreateTargets(this, insights);
var riskTargetOverrides = RiskManagement.ManageRisk(this);
// execute on the targets, overriding targets for symbols w/ risk targets
Execution.Execute(this, riskTargetOverrides.Concat(targets).DistinctBy(pt => pt.Symbol));
}
/// <summary>
/// Used to send security changes to algorithm framework models
/// </summary>
/// <param name="changes">Security additions/removals for this time step</param>
public sealed override void OnFrameworkSecuritiesChanged(SecurityChanges changes)
{
Alpha.OnSecuritiesChanged(this, changes);
PortfolioConstruction.OnSecuritiesChanged(this, changes);
Execution.OnSecuritiesChanged(this, changes);
RiskManagement.OnSecuritiesChanged(this, changes);
}
/// <summary>
/// Sets the portfolio selection model
/// </summary>
/// <param name="portfolioSelection">Model defining universes for the algorithm</param>
public void SetPortfolioSelection(IPortfolioSelectionModel portfolioSelection)
{
PortfolioSelection = portfolioSelection;
}
/// <summary>
/// Sets the alpha model
/// </summary>
/// <param name="alpha">Model that generates alpha</param>
public void SetAlpha(IAlphaModel alpha)
{
Alpha = alpha;
}
/// <summary>
/// Sets the portfolio construction model
/// </summary>
/// <param name="portfolioConstruction">Model defining how to build a portoflio from insights</param>
public void SetPortfolioConstruction(IPortfolioConstructionModel portfolioConstruction)
{
PortfolioConstruction = portfolioConstruction;
}
/// <summary>
/// Sets the execution model
/// </summary>
/// <param name="execution">Model defining how to execute trades to reach a portfolio target</param>
public void SetExecution(IExecutionModel execution)
{
Execution = execution;
}
/// <summary>
/// Sets the risk management model
/// </summary>
/// <param name="riskManagement">Model defining </param>
public void SetRiskManagement(IRiskManagementModel riskManagement)
{
RiskManagement = riskManagement;
}
private Insight SetGeneratedAndClosedTimes(Insight insight)
{
insight.GeneratedTimeUtc = UtcTime;
insight.ReferenceValue = _securityValuesProvider.GetValues(insight.Symbol).Get(insight.Type);
TimeSpan barSize;
Security security;
SecurityExchangeHours exchangeHours;
if (Securities.TryGetValue(insight.Symbol, out security))
{
exchangeHours = security.Exchange.Hours;
barSize = security.Resolution.ToTimeSpan();
}
else
{
barSize = insight.Period.ToHigherResolutionEquivalent(false).ToTimeSpan();
exchangeHours = MarketHoursDatabase.GetExchangeHours(insight.Symbol.ID.Market, insight.Symbol, insight.Symbol.SecurityType);
}
var localStart = UtcTime.ConvertFromUtc(exchangeHours.TimeZone);
barSize = QuantConnect.Time.Max(barSize, QuantConnect.Time.OneMinute);
var barCount = (int) (insight.Period.Ticks / barSize.Ticks);
insight.CloseTimeUtc = QuantConnect.Time.GetEndTimeForTradeBars(exchangeHours, localStart, barSize, barCount, false).ConvertToUtc(exchangeHours.TimeZone);
return insight;
}
private void CheckModels()
{
if (PortfolioSelection == null)
{
throw new Exception("Framework algorithms must specify a portfolio selection model using the 'PortfolioSelection' property.");
}
if (Alpha == null)
{
throw new Exception("Framework algorithms must specify a alpha model using the 'Alpha' property.");
}
if (PortfolioConstruction == null)
{
throw new Exception("Framework algorithms must specify a portfolio construction model using the 'PortfolioConstruction' property");
}
if (Execution == null)
{
throw new Exception("Framework algorithms must specify an execution model using the 'Execution' property.");
}
if (RiskManagement == null)
{
throw new Exception("Framework algorithms must specify an risk management model using the 'RiskManagement' property.");
}
}
}
}