Dispose of python algorithm instance (#8695)
Syntax Tests / build (push) Has been cancelled
Python Virtual Environments / build (push) Has been cancelled
API Tests / build (push) Has been cancelled
Benchmarks / build (push) Has been cancelled
Build & Test Lean / build (push) Has been cancelled
Regression Tests / build (push) Has been cancelled
Report Generator Tests / build (push) Has been cancelled
Research Regression Tests / build (push) Has been cancelled

This commit is contained in:
Martin-Molinero
2025-04-15 11:33:33 -03:00
committed by GitHub
parent a1302d2bcd
commit c130bb2de4
4 changed files with 71 additions and 28 deletions
@@ -47,7 +47,6 @@ namespace QuantConnect.AlgorithmFactory.Python.Wrappers
/// </summary>
public class AlgorithmPythonWrapper : BasePythonWrapper<IAlgorithm>, IAlgorithm
{
private readonly PyObject _algorithm;
private readonly dynamic _onData;
private readonly dynamic _onMarginCall;
private readonly IAlgorithm _baseAlgorithm;
@@ -110,9 +109,8 @@ namespace QuantConnect.AlgorithmFactory.Python.Wrappers
{
Logging.Log.Trace("AlgorithmPythonWrapper(): Creating IAlgorithm instance.");
_algorithm = attr.Invoke();
SetPythonInstance(_algorithm);
var dynAlgorithm = _algorithm as dynamic;
SetPythonInstance(attr.Invoke());
var dynAlgorithm = Instance as dynamic;
// Set pandas
dynAlgorithm.SetPandasConverter();
@@ -122,11 +120,11 @@ namespace QuantConnect.AlgorithmFactory.Python.Wrappers
// determines whether OnData method was defined or inherits from QCAlgorithm
// If it is not, OnData from the base class will not be called
_onData = _algorithm.GetPythonMethod("OnData");
_onData = Instance.GetPythonMethod("OnData");
_onMarginCall = _algorithm.GetPythonMethod("OnMarginCall");
_onMarginCall = Instance.GetPythonMethod("OnMarginCall");
PyObject endOfDayMethod = _algorithm.GetPythonMethod("OnEndOfDay");
using PyObject endOfDayMethod = Instance.GetPythonMethod("OnEndOfDay");
if (endOfDayMethod != null)
{
// Since we have a EOD method implemented
@@ -148,27 +146,27 @@ namespace QuantConnect.AlgorithmFactory.Python.Wrappers
}
// Initialize the python methods
_onBrokerageDisconnect = _algorithm.GetMethod("OnBrokerageDisconnect");
_onBrokerageMessage = _algorithm.GetMethod("OnBrokerageMessage");
_onBrokerageReconnect = _algorithm.GetMethod("OnBrokerageReconnect");
_onSplits = _algorithm.GetMethod("OnSplits");
_onDividends = _algorithm.GetMethod("OnDividends");
_onDelistings = _algorithm.GetMethod("OnDelistings");
_onSymbolChangedEvents = _algorithm.GetMethod("OnSymbolChangedEvents");
_onEndOfDay = _algorithm.GetMethod("OnEndOfDay");
_onCommand = _algorithm.GetMethod("OnCommand");
_onMarginCallWarning = _algorithm.GetMethod("OnMarginCallWarning");
_onOrderEvent = _algorithm.GetMethod("OnOrderEvent");
_onAssignmentOrderEvent = _algorithm.GetMethod("OnAssignmentOrderEvent");
_onSecuritiesChanged = _algorithm.GetMethod("OnSecuritiesChanged");
_onFrameworkSecuritiesChanged = _algorithm.GetMethod("OnFrameworkSecuritiesChanged");
_onBrokerageDisconnect = Instance.GetMethod("OnBrokerageDisconnect");
_onBrokerageMessage = Instance.GetMethod("OnBrokerageMessage");
_onBrokerageReconnect = Instance.GetMethod("OnBrokerageReconnect");
_onSplits = Instance.GetMethod("OnSplits");
_onDividends = Instance.GetMethod("OnDividends");
_onDelistings = Instance.GetMethod("OnDelistings");
_onSymbolChangedEvents = Instance.GetMethod("OnSymbolChangedEvents");
_onEndOfDay = Instance.GetMethod("OnEndOfDay");
_onCommand = Instance.GetMethod("OnCommand");
_onMarginCallWarning = Instance.GetMethod("OnMarginCallWarning");
_onOrderEvent = Instance.GetMethod("OnOrderEvent");
_onAssignmentOrderEvent = Instance.GetMethod("OnAssignmentOrderEvent");
_onSecuritiesChanged = Instance.GetMethod("OnSecuritiesChanged");
_onFrameworkSecuritiesChanged = Instance.GetMethod("OnFrameworkSecuritiesChanged");
}
attr.Dispose();
}
module.Dispose();
pyList.Dispose();
// If _algorithm could not be set, throw exception
if (_algorithm == null)
if (Instance == null)
{
throw new Exception("Please ensure that one class inherits from QCAlgorithm.");
}
@@ -1163,13 +1161,13 @@ namespace QuantConnect.AlgorithmFactory.Python.Wrappers
/// <returns></returns>
public override string ToString()
{
if (_algorithm == null)
if (Instance == null)
{
return base.ToString();
}
using (Py.GIL())
{
return _algorithm.Repr();
return Instance.Repr();
}
}
@@ -1270,5 +1268,30 @@ namespace QuantConnect.AlgorithmFactory.Python.Wrappers
/// <returns>The command result</returns>
public CommandResultPacket RunCommand(CallbackCommand command) => _baseAlgorithm.RunCommand(command);
/// <summary>
/// Dispose of this instance
/// </summary>
public override void Dispose()
{
using var _ = Py.GIL();
_onBrokerageDisconnect?.Dispose();
_onBrokerageMessage?.Dispose();
_onBrokerageReconnect?.Dispose();
_onSplits?.Dispose();
_onDividends?.Dispose();
_onDelistings?.Dispose();
_onSymbolChangedEvents?.Dispose();
_onEndOfDay?.Dispose();
_onMarginCallWarning?.Dispose();
_onOrderEvent?.Dispose();
_onCommand?.Dispose();
_onAssignmentOrderEvent?.Dispose();
_onSecuritiesChanged?.Dispose();
_onFrameworkSecuritiesChanged?.Dispose();
_onData?.Dispose();
_onMarginCall?.Dispose();
base.Dispose();
}
}
}