LEAN基础模块QuantConnect.Logging

一、背景介绍

LEAN是一个算法交易引擎。基于C#语言。QuantConnect.Logging为LEAN基础模块,提供日志功能。下面分析实现细节,并分享使用。

二、类关系结构图

三、核心类介绍

1、QuantConnect.Logging.LogEntry

      标识一条日志。

using System;

namespace QuantConnect.Logging
{
    /******************************************************** 
    * CLASS DEFINITION
    *********************************************************/
    /// <summary>
    /// Log entry wrapper to make logging simpler:
    /// </summary>
    public class LogEntry
    {
        /******************************************************** 
        * CLASS PROPERTIES
        *********************************************************/
        /// <summary>
        /// Time of the log entry
        /// </summary>
        public DateTime Time;

        /// <summary>
        /// Message of the log entry
        /// </summary>
        public string Message;

        /******************************************************** 
        * CLASS CONSTRUCTOR
        *********************************************************/
        /// <summary>
        /// Create a default log message with the current time.
        /// </summary>
        /// <param name="message"></param>
        public LogEntry(string message)
        {
            Time = DateTime.UtcNow;
            Message = message;
        }

        /// <summary>
        /// Create a log entry at a specific time in the analysis (for a backtest).
        /// </summary>
        /// <param name="message">Message for log</param>
        /// <param name="time">Time of the message</param>
        public LogEntry(string message, DateTime time)
        {
            Time = time.ToUniversalTime();
            Message = message;
        }
    }
}

2、QuantConnect.Logging.ILogHandler

       日志处理接口类。

using System;

namespace QuantConnect.Logging
{
    /// <summary>
    /// Interface for redirecting log output
    /// </summary>
    public interface ILogHandler : IDisposable
    {
        /// <summary>
        /// Write error message to log
        /// </summary>
        /// <param name="text">The error text to log</param>
        void Error(string text);
       
        /// <summary>
        /// Write debug message to log
        /// </summary>
        /// <param name="text">The debug text to log</param>
        void Debug(string text);
       
        /// <summary>
        /// Write debug message to log
        /// </summary>
        /// <param name="text">The trace text to log</param>
        void Trace(string text);
    }
}

3、QuantConnect.Logging.Log

      日志记录接口。

/**********************************************************
* USING NAMESPACES
**********************************************************/
using System;
using System.Threading;
using System.Text;
using System.Collections;
using System.Diagnostics;
using System.IO;

namespace QuantConnect.Logging 
{

    /******************************************************** 
    * CLASS DEFINITIONS
    *********************************************************/
    /// <summary>
    /// Logging management class.
    /// </summary>
    public static class Log
    {
        /******************************************************** 
        * CLASS VARIABLES
        *********************************************************/
        private static string _lastTraceText = "";
        private static string _lastErrorText = "";
        private static bool _debuggingEnabled;
        private static int _level = 1;
        private static ILogHandler _logHandler = new ConsoleLogHandler();

        /******************************************************** 
        * CLASS PROPERTIES
        *********************************************************/

        /// <summary>
        /// Gets or sets the ILogHandler instance used as the global logging implementation.
        /// </summary>
        public static ILogHandler LogHandler
        {
            get { return _logHandler; }
            set { _logHandler = value; }
        }


        /// <summary>
        /// Global flag whether to enable debugging logging:
        /// </summary>
        public static bool DebuggingEnabled
        {
            get { return _debuggingEnabled; }
            set { _debuggingEnabled = value; }
        }


        /// <summary>
        /// Set the minimum message level:
        /// </summary>
        public static int DebuggingLevel
        {
            get { return _level; }
            set { _level = value; }
        }

        /******************************************************** 
        * CLASS METHODS
        *********************************************************/
        /// <summary>
        /// Log error
        /// </summary>
        /// <param name="error">String Error</param>
        /// <param name="overrideMessageFloodProtection">Force sending a message, overriding the "do not flood" directive</param>
        public static void Error(string error, bool overrideMessageFloodProtection = false) 
        {
            try 
            {
                if (error == _lastErrorText && !overrideMessageFloodProtection) return;
                _logHandler.Error(error);
                _lastErrorText = error; //Stop message flooding filling diskspace.
            } 
            catch (Exception err)
            {
                Console.WriteLine("Log.Error(): Error writing error: " + err.Message);
            }
        }


        /// <summary>
        /// Log trace
        /// </summary>
        public static void Trace(string traceText, bool overrideMessageFloodProtection = false) 
        { 
            try 
            {
                if (traceText == _lastTraceText && !overrideMessageFloodProtection) return;
                _logHandler.Trace(traceText);
                _lastTraceText = traceText;
            } 
            catch (Exception err) 
            {
                Console.WriteLine("Log.Trace(): Error writing trace: "  +err.Message);
            }
        }

        /// <summary>
        /// Output to the console, and sleep the thread for a little period to monitor the results.
        /// </summary>
        /// <param name="text"></param>
        /// <param name="level">debug level</param>
        /// <param name="delay"></param>
        public static void Debug(string text, int level = 1, int delay = 0)
        {
            try
            {
                if (!_debuggingEnabled || level < _level) return;
                _logHandler.Debug(text);
                Thread.Sleep(delay);
            }
            catch (Exception err)
            {
                Console.WriteLine("Log.Debug(): Error writing debug: " + err.Message);
            }
        }

        /// <summary>
        /// C# Equivalent of Print_r in PHP:
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="recursion"></param>
        /// <returns></returns>
        public static string VarDump(object obj, int recursion = 0) 
        {
            var result = new StringBuilder();

            // Protect the method against endless recursion
            if (recursion < 5)
            {
                // Determine object type
                var t = obj.GetType();

                // Get array with properties for this object
                var properties = t.GetProperties();

                foreach (var property in properties) 
                {
                    try
                    {
                        // Get the property value
                        var value = property.GetValue(obj, null);

                        // Create indenting string to put in front of properties of a deeper level
                        // We'll need this when we display the property name and value
                        var indent = String.Empty;
                        var spaces = "|   ";
                        var trail = "|...";

                        if (recursion > 0) 
                        {
                            indent = new StringBuilder(trail).Insert(0, spaces, recursion - 1).ToString();
                        }

                        if (value != null) 
                        {
                            // If the value is a string, add quotation marks
                            var displayValue = value.ToString();
                            if (value is string) displayValue = String.Concat('"', displayValue, '"');

                            // Add property name and value to return string
                            result.AppendFormat("{0}{1} = {2}\n", indent, property.Name, displayValue);

                            try 
                            {
                                if (!(value is ICollection)) 
                                {
                                    // Call var_dump() again to list child properties
                                    // This throws an exception if the current property value
                                    // is of an unsupported type (eg. it has not properties)
                                    result.Append(VarDump(value, recursion + 1));
                                } 
                                else 
                                {
                                    // 2009-07-29: added support for collections
                                    // The value is a collection (eg. it's an arraylist or generic list)
                                    // so loop through its elements and dump their properties
                                    var elementCount = 0;
                                    foreach (var element in ((ICollection)value)) 
                                    {
                                        var elementName = String.Format("{0}[{1}]", property.Name, elementCount);
                                        indent = new StringBuilder(trail).Insert(0, spaces, recursion).ToString();

                                        // Display the collection element name and type
                                        result.AppendFormat("{0}{1} = {2}\n", indent, elementName, element.ToString());

                                        // Display the child properties
                                        result.Append(VarDump(element, recursion + 2));
                                        elementCount++;
                                    }

                                    result.Append(VarDump(value, recursion + 1));
                                }
                            } catch { }
                        } 
                        else 
                        {
                            // Add empty (null) property to return string
                            result.AppendFormat("{0}{1} = {2}\n", indent, property.Name, "null");
                        }
                    } 
                    catch 
                    {
                        // Some properties will throw an exception on property.GetValue()
                        // I don't know exactly why this happens, so for now i will ignore them...
                    }
                }
            }

            return result.ToString();
        }
    }
}

四、使用

在LEAN中,其他模块都依赖QuantConnect.Logging模块。通过QuantConnect.Logging.Log类的Error()\Trace()\Debug()方法,记录日志。

五、扩展

如果需要个性的日志处理,可以实现QuantConnect.Logging.ILogHandler接口,对日志进行个性处理。可以参考现有实现QuantConnect.Logging.FileLogHandler.cs。然后通过设置QuantConnect.Logging.Log中LogHandler为新实现。

综上,QuantConnect.Logging模块作为基础模块,给LEAN系统提供了日志功能。在设计上考虑了扩展。(C#生态有可重用的日志模块吗?)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值