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))); }
/// <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)}"); } }
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")); }
/// <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)}"); } }
/// <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())); }
/// <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); }
/// <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)}"); } }