public void CreatesFromAssemblies()
        {
            var assembly  = typeof(FakeExceptionInterpreter).Assembly;
            var projector = StackExceptionInterpreter.CreateFromAssemblies(new[] { assembly });

            Assert.AreEqual(1, projector.Interpreters.Count(p => p.GetType() == typeof(FakeExceptionInterpreter)));
        }
Example #2
0
        /// <summary>
        /// <see cref = "AlgorithmPythonWrapper"/> constructor.
        /// Creates and wraps the algorithm written in python.
        /// </summary>
        /// <param name="moduleName">Name of the module that can be found in the PYTHONPATH</param>
        public AlgorithmPythonWrapper(string moduleName)
        {
            try
            {
                using (Py.GIL())
                {
                    Logging.Log.Trace($"AlgorithmPythonWrapper(): Python version {PythonEngine.Version}: Importing python module {moduleName}");

                    var module = Py.Import(moduleName);
                    var pyList = module.Dir();
                    foreach (var name in pyList)
                    {
                        Type type;
                        var  attr = module.GetAttr(name.ToString());
                        var  repr = attr.Repr().GetStringBetweenChars('\'', '\'');

                        if (repr.StartsWith(moduleName) &&                // Must be defined in the module
                            attr.TryConvert(out type) &&                  // Must be a Type
                            typeof(QCAlgorithm).IsAssignableFrom(type))   // Must inherit from QCAlgorithm
                        {
                            Logging.Log.Trace("AlgorithmPythonWrapper(): Creating IAlgorithm instance.");

                            _algorithm = attr.Invoke();

                            // Set pandas
                            _algorithm.SetPandasConverter();

                            // IAlgorithm reference for LEAN internal C# calls (without going from C# to Python and back)
                            _baseAlgorithm = _algorithm.AsManagedObject(type);

                            // determines whether OnData method was defined or inherits from QCAlgorithm
                            // If it is not, OnData from the base class will not be called
                            var pyAlgorithm = _algorithm as PyObject;
                            _onData = pyAlgorithm.GetPythonMethod("OnData");

                            _onMarginCall = pyAlgorithm.GetPythonMethod("OnMarginCall");

                            _onOrderEvent = pyAlgorithm.GetAttr("OnOrderEvent");
                        }
                        attr.Dispose();
                    }
                    module.Dispose();
                    pyList.Dispose();
                    // If _algorithm could not be set, throw exception
                    if (_algorithm == null)
                    {
                        throw new Exception("Please ensure that one class inherits from QCAlgorithm.");
                    }
                }
            }
            catch (Exception e)
            {
                // perform exception interpretation for error in module import
                var interpreter = StackExceptionInterpreter.CreateFromAssemblies(AppDomain.CurrentDomain.GetAssemblies());
                e = interpreter.Interpret(e, interpreter);

                throw new Exception($"AlgorithmPythonWrapper(): {interpreter.GetExceptionMessageHeader(e)}");
            }
        }
Example #3
0
        public void VerifyMessageContainsStackTraceInformation()
        {
            var exception   = CreateExceptionFromType(typeof(PythonException));
            var assembly    = typeof(PythonExceptionInterpreter).Assembly;
            var interpreter = StackExceptionInterpreter.CreateFromAssemblies(new[] { assembly });

            exception = interpreter.Interpret(exception, NullExceptionInterpreter.Instance);
            Assert.True(exception.Message.Contains("x = 01"));
        }
Example #4
0
        /// <summary>
        /// <see cref = "AlgorithmPythonWrapper"/> constructor.
        /// Creates and wraps the algorithm written in python.
        /// </summary>
        /// <param name="moduleName">Name of the module that can be found in the PYTHONPATH</param>
        public AlgorithmPythonWrapper(string moduleName)
        {
            try
            {
                using (Py.GIL())
                {
                    Logging.Log.Trace($"AlgorithmPythonWrapper(): Python version {PythonEngine.Version}: Importing python module {moduleName}");

                    var module = Py.Import(moduleName);

                    foreach (var name in module.Dir())
                    {
                        Type type;
                        var  attr = module.GetAttr(name.ToString());
                        var  repr = attr.Repr().GetStringBetweenChars('\'', '\'');

                        if (repr.StartsWith(moduleName) &&                // Must be defined in the module
                            attr.TryConvert(out type) &&                  // Must be a Type
                            typeof(QCAlgorithm).IsAssignableFrom(type))   // Must inherit from QCAlgorithm
                        {
                            Logging.Log.Trace("AlgorithmPythonWrapper(): Creating IAlgorithm instance.");

                            _algorithm = attr.Invoke();

                            // Set pandas
                            _algorithm.SetPandasConverter();

                            // IAlgorithm reference for LEAN internal C# calls (without going from C# to Python and back)
                            _baseAlgorithm = _algorithm.AsManagedObject(type);

                            // write events such that when the base handles an event it
                            // will also invoke event handlers defined on this instance
                            _baseAlgorithm.InsightsGenerated += InsightsGenerated;

                            // determines whether OnData method was defined or inherits from QCAlgorithm
                            // If it is not, OnData from the base class will not be called
                            var pythonType = (_algorithm as PyObject).GetAttr("OnData").GetPythonType();
                            _isOnDataDefined = pythonType.Repr().Equals("<class \'method\'>");
                        }
                    }

                    // If _algorithm could not be set, throw exception
                    if (_algorithm == null)
                    {
                        throw new Exception("Please ensure that one class inherits from QCAlgorithm or QCAlgorithmFramework.");
                    }
                }
            }
            catch (Exception e)
            {
                // perform exception interpretation for error in module import
                var interpreter = StackExceptionInterpreter.CreateFromAssemblies(AppDomain.CurrentDomain.GetAssemblies());
                e = interpreter.Interpret(e, interpreter);

                throw new Exception($"AlgorithmPythonWrapper(): {interpreter.GetExceptionMessageHeader(e)}");
            }
        }
Example #5
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Engine"/> class using the specified handlers
 /// </summary>
 /// <param name="systemHandlers">The system handlers for controlling acquisition of jobs, messaging, and api calls</param>
 /// <param name="algorithmHandlers">The algorithm handlers for managing algorithm initialization, data, results, transaction, and real time events</param>
 /// <param name="liveMode">True when running in live mode, false otherwise</param>
 public Engine(LeanEngineSystemHandlers systemHandlers, LeanEngineAlgorithmHandlers algorithmHandlers, bool liveMode)
 {
     _liveMode         = liveMode;
     SystemHandlers    = systemHandlers;
     AlgorithmHandlers = algorithmHandlers;
     // this is slow, so we will do it on demand
     _exceptionInterpreter = new Lazy <StackExceptionInterpreter>(() =>
                                                                  StackExceptionInterpreter.CreateFromAssemblies(AppDomain.CurrentDomain.GetAssemblies()));
 }
        public void RecursivelyFlattensExceptionMessages()
        {
            var inner   = new Exception("inner");
            var middle  = new Exception("middle", inner);
            var outter  = new Exception("outter", middle);
            var message = new StackExceptionInterpreter(Enumerable.Empty <IExceptionInterpreter>()).ToString(outter);

            Assert.AreEqual("outter middle inner", message);
        }
Example #7
0
        /// <summary>
        /// Create a new instance of a python algorithm
        /// </summary>
        /// <param name="assemblyPath"></param>
        /// <param name="algorithmInstance"></param>
        /// <param name="errorMessage"></param>
        /// <returns></returns>
        private bool TryCreatePythonAlgorithm(string assemblyPath, out IAlgorithm algorithmInstance, out string errorMessage)
        {
            algorithmInstance = null;
            errorMessage      = string.Empty;

            //File does not exist.
            if (!File.Exists(assemblyPath))
            {
                errorMessage = $"Loader.TryCreatePythonAlgorithm(): Unable to find py file: {assemblyPath}";
                return(false);
            }

            try
            {
                var pythonFile = new FileInfo(assemblyPath);
                var moduleName = pythonFile.Name.Replace(".pyc", "").Replace(".py", "");

                //Help python find the module
                Environment.SetEnvironmentVariable("PYTHONPATH", pythonFile.DirectoryName);

                // Initialize Python Engine
                if (!PythonEngine.IsInitialized)
                {
                    PythonEngine.Initialize();
                    PythonEngine.BeginAllowThreads();
                }

                // Import Python module
                using (Py.GIL())
                {
                    Log.Trace($"Loader.TryCreatePythonAlgorithm(): Python version {PythonEngine.Version}: Importing python module {moduleName}");
                    var module = Py.Import(moduleName);

                    if (module == null)
                    {
                        errorMessage = $"Loader.TryCreatePythonAlgorithm(): Unable to import python module {assemblyPath}. Check for errors in the python scripts.";
                        return(false);
                    }

                    Log.Trace("Loader.TryCreatePythonAlgorithm(): Creating IAlgorithm instance.");

                    algorithmInstance = new AlgorithmPythonWrapper(module);
                }
            }
            catch (Exception e)
            {
                // perform exception interpretation for error in module import
                var interpreter = StackExceptionInterpreter.CreateFromAssemblies(AppDomain.CurrentDomain.GetAssemblies());
                e = interpreter.Interpret(e, interpreter);

                Log.Error(e);
                errorMessage = $"Loader.TryCreatePythonAlgorithm(): Unable to import python module {assemblyPath}. {interpreter.GetExceptionMessageHeader(e)}";
            }

            //Successful load.
            return(algorithmInstance != null);
        }
        public void CallsInterpretOnFirstProjectionThatCanInterpret()
        {
            var canInterpretCalled = new List <int>();
            var interpretCalled    = new List <int>();
            var interpreters       = new[]
            {
                new FakeExceptionInterpreter(e =>
                {
                    canInterpretCalled.Add(0);
                    return(false);
                }, e =>
                {
                    interpretCalled.Add(0);
                    return(e);
                },
                                             order: 2),
                new FakeExceptionInterpreter(e =>
                {
                    canInterpretCalled.Add(1);
                    return(true);
                }, e =>
                {
                    interpretCalled.Add(1);
                    return(e);
                },
                                             order: 1),
                new FakeExceptionInterpreter(e =>
                {
                    canInterpretCalled.Add(2);
                    return(false);
                }, e =>
                {
                    interpretCalled.Add(2);
                    return(e);
                },
                                             order: 0)
            };

            var interpreter = new StackExceptionInterpreter(interpreters);

            interpreter.Interpret(new Exception(), null);

            // can interpret called for 3nd and 2rd entry
            Assert.Contains(2, canInterpretCalled);
            Assert.Contains(1, canInterpretCalled);
            Assert.That(canInterpretCalled, Is.Not.Contains(0));

            // interpret only called on second entry
            Assert.That(interpretCalled, Is.Not.Contains(0));
            Assert.Contains(1, interpretCalled);
            Assert.That(interpretCalled, Is.Not.Contains(2));

            // interpreter called 3rd before 2nd
            Assert.Greater(canInterpretCalled.First(), canInterpretCalled.Last());
        }
        public void GetsExceptionMessageHeaderAsAllInnersJoinedBySpace()
        {
            var inner   = new Exception("inner");
            var middle  = new Exception("middle", inner);
            var outter  = new Exception("outter", middle);
            var message = new StackExceptionInterpreter(Enumerable.Empty <IExceptionInterpreter>()).GetExceptionMessageHeader(outter);

            // header line w/ exception message and then the full detail on a new line
            var expectedMessage = "outter middle inner";

            Assert.AreEqual(expectedMessage, message);
        }
        public void CallsInterpretOnFirstProjectionThatCanInterpret()
        {
            var canInterpretCalled = new List <int>();
            var interpretCalled    = new List <int>();
            var interpreters       = new[]
            {
                new FakeExceptionInterpreter(e =>
                {
                    canInterpretCalled.Add(0);
                    return(false);
                }, e =>
                {
                    interpretCalled.Add(0);
                    return(e);
                }),
                new FakeExceptionInterpreter(e =>
                {
                    canInterpretCalled.Add(1);
                    return(true);
                }, e =>
                {
                    interpretCalled.Add(1);
                    return(e);
                }),
                new FakeExceptionInterpreter(e =>
                {
                    canInterpretCalled.Add(2);
                    return(false);
                }, e =>
                {
                    interpretCalled.Add(2);
                    return(e);
                })
            };

            var projector = new StackExceptionInterpreter(interpreters);

            projector.Interpret(new Exception(), null);

            // can project called for 1st and second entry
            Assert.Contains(0, canInterpretCalled);
            Assert.Contains(1, canInterpretCalled);
            Assert.That(canInterpretCalled, Is.Not.Contains(2));

            // project only called on second entry
            Assert.That(interpretCalled, Is.Not.Contains(0));
            Assert.Contains(1, interpretCalled);
            Assert.That(interpretCalled, Is.Not.Contains(2));
        }
        public void RecursivelyProjectsInnerExceptions()
        {
            var inner       = new Exception("inner");
            var middle      = new Exception("middle", inner);
            var outter      = new Exception("outter", middle);
            var interpreter = new StackExceptionInterpreter(new[]
            {
                new FakeExceptionInterpreter()
            });

            var interpreted = interpreter.Interpret(outter, null);

            Assert.AreEqual("Projected 1: outter", interpreted.Message);
            Assert.AreEqual("Projected 2: middle", interpreted.InnerException.Message);
            Assert.AreEqual("Projected 3: inner", interpreted.InnerException.InnerException.Message);
        }
Example #12
0
        /// <summary>
        /// <see cref = "AlgorithmPythonWrapper"/> constructor.
        /// Creates and wraps the algorithm written in python.
        /// </summary>
        /// <param name="moduleName">Name of the module that can be found in the PYTHONPATH</param>
        public AlgorithmPythonWrapper(string moduleName)
        {
            try
            {
                using (Py.GIL())
                {
                    Logging.Log.Trace($"AlgorithmPythonWrapper(): Python version {PythonEngine.Version}: Importing python module {moduleName}");

                    var module = Py.Import(moduleName);

                    Logging.Log.Trace($"AlgorithmPythonWrapper(): {moduleName} successfully imported.");

                    var pyList = module.Dir();
                    foreach (var name in pyList)
                    {
                        Type type;
                        var  attr = module.GetAttr(name.ToString());
                        var  repr = attr.Repr().GetStringBetweenChars('\'', '\'');

                        if (repr.StartsWith(moduleName) &&                // Must be defined in the module
                            attr.TryConvert(out type) &&                  // Must be a Type
                            typeof(QCAlgorithm).IsAssignableFrom(type))   // Must inherit from QCAlgorithm
                        {
                            Logging.Log.Trace("AlgorithmPythonWrapper(): Creating IAlgorithm instance.");

                            _algorithm = attr.Invoke();

                            // Set pandas
                            _algorithm.SetPandasConverter();

                            // IAlgorithm reference for LEAN internal C# calls (without going from C# to Python and back)
                            _baseAlgorithm = _algorithm.AsManagedObject(type);

                            // determines whether OnData method was defined or inherits from QCAlgorithm
                            // If it is not, OnData from the base class will not be called
                            var pyAlgorithm = _algorithm as PyObject;
                            _onData = pyAlgorithm.GetPythonMethod("OnData");

                            _onMarginCall = pyAlgorithm.GetPythonMethod("OnMarginCall");

                            _onOrderEvent = pyAlgorithm.GetAttr("OnOrderEvent");

                            PyObject endOfDayMethod = pyAlgorithm.GetPythonMethod("OnEndOfDay");
                            if (endOfDayMethod != null)
                            {
                                // Since we have a EOD method implemented
                                // Determine which one it is by inspecting its arg count
                                var argCount = endOfDayMethod.GetPythonArgCount();
                                switch (argCount)
                                {
                                case 0:     // EOD()
                                    IsOnEndOfDayImplemented = true;
                                    break;

                                case 1:     // EOD(Symbol)
                                    IsOnEndOfDaySymbolImplemented = true;
                                    break;
                                }

                                // Its important to note that even if both are implemented
                                // python will only use the last implemented, meaning only one will
                                // be used and seen.
                            }
                        }
                        attr.Dispose();
                    }
                    module.Dispose();
                    pyList.Dispose();
                    // If _algorithm could not be set, throw exception
                    if (_algorithm == null)
                    {
                        throw new Exception("Please ensure that one class inherits from QCAlgorithm.");
                    }
                }
            }
            catch (Exception e)
            {
                // perform exception interpretation for error in module import
                var interpreter = StackExceptionInterpreter.CreateFromAssemblies(AppDomain.CurrentDomain.GetAssemblies());
                e = interpreter.Interpret(e, interpreter);

                throw new Exception($"AlgorithmPythonWrapper(): {interpreter.GetExceptionMessageHeader(e)}");
            }
        }