</pre>转载需注明出处:<a target=_blank href="http://blog.csdn.net/minimicall?viewmode=contents">http://blog.csdn.net/minimicall?viewmode=contents</a>,<a target=_blank href="http://cloudtrade.top/">http://cloudtrade.top/</a></p><p></p><p>上一节已经说明了实时事件和处理接口。这一节需要说明回测里面的实时事件处理。主要是开启一个新的线程来处理定时事件。例如每天开市的时候的事件和每天闭市时候触发的事件。还有你可以定义任意一个给定时间的事件。</p><p>下面我们通过代码来说 明问题</p><p><pre name="code" class="csharp">/* * 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.Threading; using QuantConnect.Interfaces; using QuantConnect.Packets; using QuantConnect.Logging; namespace QuantConnect.Lean.Engine.RealTime { /// <summary> /// Psuedo realtime event processing for backtesting to simulate realtime events in fast forward. /// 伪实时事件处理,为回归测试实时事件(快进) /// </summary> public class BacktestingRealTimeHandler : IRealTimeHandler { /******************************************************** * PRIVATE VARIABLES *********************************************************/ //Threading private DateTime _time = new DateTime(); private bool _exitTriggered; private bool _isActive = true; private AlgorithmNodePacket _job;//相关任务 //Events: private List<RealTimeEvent> _events; //Algorithm and Handlers: private IAlgorithm _algorithm;//相关算法 private Dictionary<SecurityType, MarketToday> _today;//今日市场 /******************************************************** * PUBLIC PROPERTIES *********************************************************/ /// <summary> /// Realtime Moment. /// </summary> public DateTime Time { get { return _time; } } /// <summary> /// Events array we scan to trigger realtime events. /// </summary> public List<RealTimeEvent> Events { get { return _events; } } /// <summary> /// Flag indicating the hander thread is completely finished and ready to dispose. /// </summary> public bool IsActive { get { return _isActive; } } /// <summary> /// Market hours for today for each security type in the algorithm /// 为算法中每种证券类型的今日交易时间(例如股票和黄金的交易时间就不一样的,如果该算法涉及到这两种证券类型) /// </summary> public Dictionary<SecurityType, MarketToday> MarketToday { get { throw new NotImplementedException("MarketToday is not currently needed in backtesting mode");//回归测试不需要 return _today; } } /******************************************************** * PUBLIC CONSTRUCTOR *********************************************************/ /// <summary> /// Setup the algorithm data, cash, job start end date etc. /// 设置算法数据、现金、任务开始和结束时间等信息,通过algorithm和job即可 /// </summary> public BacktestingRealTimeHandler(IAlgorithm algorithm, AlgorithmNodePacket job) { //Initialize: _algorithm = algorithm; _events = new List<RealTimeEvent>(); _job = job; _today = new Dictionary<SecurityType, MarketToday>(); } /******************************************************** * PUBLIC METHODS *********************************************************/ /// <summary> /// Setup the events for this date. /// 设置该日的事件 /// </summary> /// <param name="date">Date for event</param> public void SetupEvents(DateTime date) { //Clear any existing events:清除已经存在的事件 ClearEvents(); //Set up the events:设置事件 //1. Default End of Day Times: foreach (var security in _algorithm.Securities.Values)//遍历算法中涉及的每一个证券 { //Register Events:注册事件 Log.Debug("BacktestingRealTimeHandler.SetupEvents(): Adding End of Day: " + security.Exchange.MarketClose.Add(TimeSpan.FromMinutes(-10))); //1. Setup End of Day Events: //设置事件结束时间(23:50) var closingToday = date.Date + security.Exchange.MarketClose.Add(TimeSpan.FromMinutes(-10)); var symbol = security.Symbol;//证券代号 AddEvent(new RealTimeEvent( closingToday, () => {//匿名方法 try { _algorithm.OnEndOfDay(symbol);//在一天闭市的时候会调用该函数 } catch (Exception err) { Engine.ResultHandler.RuntimeError("Runtime error in OnEndOfDay event: " + err.Message, err.StackTrace); Log.Error("BacktestingRealTimeHandler.SetupEvents(): EOD: " + err.Message); } })); } // fire just before the day rolls over, 11:58pm在一天即将结束的时候调用。。。。(尼玛,和上面究竟啥子关系) AddEvent(new RealTimeEvent(date.AddHours(23.967), () => {//匿名方法 try { _algorithm.OnEndOfDay(); Log.Trace(string.Format("BacktestingRealTimeHandler: Fired On End of Day Event() for Day({0})", _time.ToShortDateString())); } catch (Exception err) { Engine.ResultHandler.RuntimeError("Runtime error in OnEndOfDay event: " + err.Message, err.StackTrace); Log.Error("BacktestingRealTimeHandler.SetupEvents.Trigger OnEndOfDay(): " + err.Message); } }, true)); } /// <summary> /// Normally this would run the realtime event monitoring. Backtesting is in fastforward so the realtime is linked to the backtest clock. /// This thread does nothing. Wait until the job is over. /// </summary> public void Run() { _isActive = false; } /// <summary> /// Add a new event to our list of events to scan. /// </summary> /// <param name="newEvent">Event object to montitor daily.</param> public void AddEvent(RealTimeEvent newEvent) { _events.Add(newEvent); } /// <summary> /// Scan the event list with the current market time and see if we need to trigger the callback. /// </summary> public void ScanEvents() { for (var i = 0; i < _events.Count; i++) { _events[i].Scan(_time); } } /// <summary> /// Clear any outstanding events. /// </summary> public void ClearEvents() { _events.Clear(); } /// <summary> /// Reset the events for a new day. /// </summary> public void ResetEvents() { for (var i = 0; i < _events.Count; i++) { _events[i].Reset(); } } /// <summary> /// Set the time for the realtime event handler. /// </summary> /// <param name="time">Current time.</param> public void SetTime(DateTime time) { //Check for day reset: if (_time.Date != time.Date) { // Backtest Mode Only: // > Scan & trigger any remaining events which haven't been triggered (e.g. daily bar data with "daily event" at 4pm): ScanEvents(); //Reset all the daily events with today's date: SetupEvents(time.Date); } //Set the time: _time = time; // Backtest Mode Only: // > Scan the event every time we set the time. This allows "fast-forwarding" of the realtime events into sync with backtest. ScanEvents(); } /// <summary> /// Stop the real time thread /// </summary> public void Exit() { _exitTriggered = true; } } // End Result Handler Thread: } // End Namespace