Skip to content

Commit fe78b8b

Browse files
committed
Addresses Peer-Review
1 parent cbf9fcb commit fe78b8b

File tree

4 files changed

+37
-16
lines changed

4 files changed

+37
-16
lines changed

Algorithm.CSharp/CustomSignalExportDemonstrationAlgorithm.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ object SimplePayload(PortfolioTarget target)
9696
}
9797

9898
/*
99+
# To test the algorithm, you can create a simple Python Flask application (app.py) and run flask
99100
# $ flask --app app run
100101
101102
# app.py:

Algorithm.Python/CustomSignalExportDemonstrationAlgorithm.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ def dispose(self):
6060
pass
6161

6262
'''
63+
# To test the algorithm, you can create a simple Python Flask application (app.py) and run flask
6364
# $ flask --app app run
6465
6566
# app.py:

Common/Algorithm/Framework/Portfolio/SignalExports/SignalExportManager.cs

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
using System;
2323
using System.Linq;
2424
using QuantConnect.Util;
25-
using QLNet;
2625

2726
namespace QuantConnect.Algorithm.Framework.Portfolio.SignalExports
2827
{
@@ -35,7 +34,7 @@ public class SignalExportManager
3534
/// <summary>
3635
/// Records the time of the first order event of a group of events
3736
/// </summary>
38-
private DateTime _initialOrderEventTimeUtc = Time.EndOfTime;
37+
private ReferenceWrapper<DateTime> _initialOrderEventTimeUtc = new(Time.EndOfTime);
3938

4039
/// <summary>
4140
/// List of signal export providers
@@ -92,12 +91,21 @@ public void AddSignalExportProvider(PyObject signalExport)
9291
/// Adds one or more new signal exports providers
9392
/// </summary>
9493
/// <param name="signalExports">One or more signal export provider</param>
95-
[Obsolete("This method is deprecated. Please use AddSignalExportProvider(ISignalExportTarget).")]
9694
public void AddSignalExportProviders(params ISignalExportTarget[] signalExports)
9795
{
9896
signalExports.DoForEach(AddSignalExportProvider);
9997
}
10098

99+
/// <summary>
100+
/// Adds one or more new signal exports providers
101+
/// </summary>
102+
/// <param name="signalExports">One or more signal export provider</param>
103+
public void AddSignalExportProviders(PyObject signalExports)
104+
{
105+
using var _ = Py.GIL();
106+
PyList.AsList(signalExports).DoForEach(AddSignalExportProvider);
107+
}
108+
101109
/// <summary>
102110
/// Sets the portfolio targets from the algorihtm's Portfolio and sends them with the
103111
/// algorithm being ran to the signal exports providers already set
@@ -215,9 +223,9 @@ private IEnumerable<PortfolioTarget> GetPortfolioTargets(decimal totalPortfolioV
215223
/// <param name="orderEvent">Event information</param>
216224
public void OnOrderEvent(OrderEvent orderEvent)
217225
{
218-
if (_initialOrderEventTimeUtc == Time.EndOfTime && orderEvent.Status.IsFill())
226+
if (_initialOrderEventTimeUtc.Value == Time.EndOfTime && orderEvent.Status.IsFill())
219227
{
220-
_initialOrderEventTimeUtc = DateTime.UtcNow;
228+
_initialOrderEventTimeUtc = new(orderEvent.UtcTime);
221229
}
222230
}
223231

@@ -227,19 +235,28 @@ public void OnOrderEvent(OrderEvent orderEvent)
227235
/// <param name="currentTimeUtc">The current time of synchronous events</param>
228236
public void Flush(DateTime currentTimeUtc)
229237
{
230-
if (_initialOrderEventTimeUtc == Time.EndOfTime || !AutomaticExportTimeSpan.HasValue)
238+
var initialOrderEventTimeUtc = _initialOrderEventTimeUtc.Value;
239+
if (initialOrderEventTimeUtc == Time.EndOfTime || !AutomaticExportTimeSpan.HasValue)
231240
{
232241
return;
233242
}
234243

235-
if (currentTimeUtc - _initialOrderEventTimeUtc < AutomaticExportTimeSpan)
244+
if (currentTimeUtc - initialOrderEventTimeUtc < AutomaticExportTimeSpan)
236245
{
237246
return;
238247
}
239-
240-
var success = SetTargetPortfolioFromPortfolio();
241-
Logging.Log.Trace($"SignalExportManager.Flush({currentTimeUtc:T}) :: Success: {success}. Initial OrderEvent Time: {_initialOrderEventTimeUtc:T}");
242-
_initialOrderEventTimeUtc = Time.EndOfTime;
248+
249+
try
250+
{
251+
SetTargetPortfolioFromPortfolio();
252+
}
253+
catch (Exception exception)
254+
{
255+
// SetTargetPortfolioFromPortfolio logs all known error on LEAN side.
256+
// Exceptions occurs in the ISignalExportTarget.Send method (user-defined).
257+
_algorithm.Error($"Failed to send portfolio target(s). Reason: {exception.Message}.{Environment.NewLine}{exception.StackTrace}");
258+
}
259+
_initialOrderEventTimeUtc = new(Time.EndOfTime);
243260
}
244261
}
245262
}

Common/Python/SignalExportTargetPythonWrapper.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@ namespace QuantConnect.Python
2222
/// <summary>
2323
/// Provides an implementation of <see cref="ISignalExportTarget"/> that wraps a <see cref="PyObject"/> object
2424
/// </summary>
25-
/// <remarks>
26-
/// Constructor for initialising the <see cref="SignalExportTargetPythonWrapper"/> class with wrapped <see cref="PyObject"/> object
27-
/// </remarks>
28-
/// <param name="model">Python benchmark model</param>
29-
public class SignalExportTargetPythonWrapper(PyObject model) : BasePythonWrapper<ISignalExportTarget>(model), ISignalExportTarget
25+
public class SignalExportTargetPythonWrapper : BasePythonWrapper<ISignalExportTarget>, ISignalExportTarget
3026
{
27+
/// <summary>
28+
/// Constructor for initialising the <see cref="SignalExportTargetPythonWrapper"/> class with wrapped <see cref="PyObject"/> object
29+
/// </summary>
30+
/// <param name="instance">The underlying python instance</param>
31+
public SignalExportTargetPythonWrapper(PyObject instance) : base(instance) { }
32+
3133
/// <summary>
3234
/// Interface to send positions holdings to different 3rd party API's
3335
/// </summary>

0 commit comments

Comments
 (0)