程序员的量化交易之路(39)--Lean之BacktestingRealTimeHandler回测实时时间事件处理7

简介:

</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


相关文章
|
4月前
|
机器人 程序员 C++
Scratch3.0——助力新进程序员理解程序(四、事件)
Scratch3.0——助力新进程序员理解程序(四、事件)
65 0
|
1月前
|
SQL IDE JavaScript
"揭秘高效代码Review秘籍:如何像侦探一样挖掘隐藏错误,提升团队编程实力,你不可错过的实战指南!"
【8月更文挑战第20天】代码Review是软件开发中提升代码质量与团队协作的关键环节。本文详细介绍高效代码Review流程:从明确范围与标准开始,到逐行审查与工具辅助,再到积极沟通与闭环管理,辅以示例确保清晰易懂。通过实践这些步骤,不仅能减少错误,还能促进知识共享,为构建高质量软件打下坚实基础。
30 2
|
1月前
|
自然语言处理 Serverless Docker
量化交易大揭秘:如何将TA-Lib神兵利器部署于云端函数计算,让策略飞升!
【8月更文挑战第8天】在量化交易中,TA-Lib作为技术分析库备受青睐,支持多语言包括Python。本教程指导如何将其移植至函数计算平台,实现云端交易策略。首先安装Python与TA-Lib;接着选择云服务商并创建实例。确认TA-Lib与平台Python版本兼容,必要时构建自定义运行时。使用`pip`安装TA-Lib并打包依赖。编写函数计算代码示例,如计算移动平均线。部署代码与依赖至平台,定制Dockerfile以支持自定义运行时。最后,通过平台测试功能验证功能正确性。完成移植后,即可享受Serverless架构的自动扩展与成本效益优势。
39 4
【开发随记】【提效】工作习惯那些事系列之四——任务管理
【开发随记】【提效】工作习惯那些事系列之四——任务管理
107 0
【开发随记】【提效】工作习惯那些事系列之四——任务管理
【开发随记】【提效】工作习惯那些事系列之五——任务处理
【开发随记】【提效】工作习惯那些事系列之五——任务处理