Skip to content

Commit 41f9d1b

Browse files
authored
Support Collective2 white-label API (#8536)
* Support Collective2 white-labe api usage * Make Collective2SignalExport Destination public and assignable * Minor comment change
1 parent c35d6ee commit 41f9d1b

File tree

3 files changed

+27
-16
lines changed

3 files changed

+27
-16
lines changed

Algorithm.CSharp/Collective2SignalExportDemonstrationAlgorithm.cs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,13 @@ public class Collective2SignalExportDemonstrationAlgorithm : QCAlgorithm, IRegre
4949
private bool _firstCall = true;
5050

5151
private PortfolioTarget[] _targets = new PortfolioTarget[4];
52-
52+
5353
/// <summary>
5454
/// Symbols accepted by Collective2. Collective2 accepts stock,
5555
/// future, forex and US stock option symbols
5656
/// </summary>
5757
private List<Symbol> _symbols = new()
58-
{
58+
{
5959
QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA, null, null),
6060
QuantConnect.Symbol.Create("EURUSD", SecurityType.Forex, Market.Oanda, null, null),
6161
QuantConnect.Symbol.CreateFuture("ES", Market.CME, new DateTime(2023, 12, 15), null),
@@ -95,15 +95,19 @@ public override void Initialize()
9595
// Initialize this flag, to check when the ema indicators crosses between themselves
9696
_emaFastIsNotSet = true;
9797

98-
// Set Collective2 signal export provider
98+
// Set Collective2 signal export provider.
99+
// If using the Collective2 white-label API, you can specify it in the constructor with the optional parameter `useWhiteLabelApi`:
100+
// e.g. new Collective2SignalExport(_collective2ApiKey, _collective2SystemId, useWhiteLabelApi: true)
101+
// The API url can also be overridden by setting the Destination property:
102+
// e.g. new Collective2SignalExport(_collective2ApiKey, _collective2SystemId) { Destination = new Uri("your url") }
99103
SignalExport.AddSignalExportProviders(new Collective2SignalExport(_collective2ApiKey, _collective2SystemId));
100104

101105
SetWarmUp(100);
102106
}
103107

104108
/// <summary>
105-
/// Reduce the quantity of holdings for SPY or increase it, depending the case,
106-
/// when the EMA's indicators crosses between themselves, then send a signal to
109+
/// Reduce the quantity of holdings for SPY or increase it, depending the case,
110+
/// when the EMA's indicators crosses between themselves, then send a signal to
107111
/// Collective2 API
108112
/// </summary>
109113
/// <param name="slice"></param>

Algorithm.Python/Collective2SignalExportDemonstrationAlgorithm.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ def initialize(self):
6161
# Collective2 System ID: This value is found beside the system's name (strategy's name) on the main system page
6262
self.collective2_system_id = 0
6363

64+
# If using the Collective2 white-label API, you can specify it in the constructor with the optional parameter `use_white_label_api`:
65+
# e.g. Collective2SignalExport(self.collective2_apikey, self.collective2_system_id, use_white_label_api=True)
66+
# The API url can also be overridden by setting the Destination property:
67+
# e.g. Collective2SignalExport(self.collective2_apikey, self.collective2_system_id) { Destination = new Uri("your url") }
6468
self.signal_export.add_signal_export_providers(Collective2SignalExport(self.collective2_apikey, self.collective2_system_id))
6569

6670
self.first_call = True

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

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,6 @@ public class Collective2SignalExport : BaseSignalExport
4141
/// </summary>
4242
private readonly int _systemId;
4343

44-
/// <summary>
45-
/// Collective2 API endpoint
46-
/// </summary>
47-
private readonly Uri _destination;
48-
4944
/// <summary>
5045
/// Algorithm being ran
5146
/// </summary>
@@ -56,6 +51,11 @@ public class Collective2SignalExport : BaseSignalExport
5651
/// </summary>
5752
private bool _isZeroPriceWarningPrinted;
5853

54+
/// <summary>
55+
/// Collective2 API endpoint
56+
/// </summary>
57+
public Uri Destination { get; set; }
58+
5959
/// <summary>
6060
/// The name of this signal export
6161
/// </summary>
@@ -83,18 +83,21 @@ public class Collective2SignalExport : BaseSignalExport
8383
/// </summary>
8484
/// <param name="apiKey">API key provided by Collective2</param>
8585
/// <param name="systemId">Trading system's ID number</param>
86-
public Collective2SignalExport(string apiKey, int systemId)
86+
/// <param name="useWhiteLabelApi">Whether to use the white-label API instead of the general one</param>
87+
public Collective2SignalExport(string apiKey, int systemId, bool useWhiteLabelApi = false)
8788
{
8889
_apiKey = apiKey;
8990
_systemId = systemId;
90-
_destination = new Uri("https://api4-general.collective2.com/Strategies/SetDesiredPositions");
91+
Destination = new Uri(useWhiteLabelApi
92+
? "https://api4-wl.collective2.com/Strategies/SetDesiredPositions"
93+
: "https://api4-general.collective2.com/Strategies/SetDesiredPositions");
9194
}
9295

9396
/// <summary>
9497
/// Creates a JSON message with the desired positions using the expected
9598
/// Collective2 API format and then sends it
9699
/// </summary>
97-
/// <param name="parameters">A list of holdings from the portfolio
100+
/// <param name="parameters">A list of holdings from the portfolio
98101
/// expected to be sent to Collective2 API and the algorithm being ran</param>
99102
/// <returns>True if the positions were sent correctly and Collective2 sent no errors, false otherwise</returns>
100103
public override bool Send(SignalExportTargetParameters parameters)
@@ -120,7 +123,7 @@ public override bool Send(SignalExportTargetParameters parameters)
120123
/// <summary>
121124
/// Converts a list of targets to a list of Collective2 positions
122125
/// </summary>
123-
/// <param name="parameters">A list of targets from the portfolio
126+
/// <param name="parameters">A list of targets from the portfolio
124127
/// expected to be sent to Collective2 API and the algorithm being ran</param>
125128
/// <param name="positions">A list of Collective2 positions</param>
126129
/// <returns>True if the given targets could be converted to a Collective2Position list, false otherwise</returns>
@@ -266,7 +269,7 @@ private bool SendPositions(string message)
266269
HttpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _apiKey);
267270

268271
//Send the message
269-
using HttpResponseMessage response = HttpClient.PostAsync(_destination, httpMessage).Result;
272+
using HttpResponseMessage response = HttpClient.PostAsync(Destination, httpMessage).Result;
270273

271274
//Parse it
272275
var responseObject = response.Content.ReadFromJsonAsync<C2Response>().Result;
@@ -333,7 +336,7 @@ private class ResponseStatus
333336
{
334337
/* Example:
335338
336-
"ResponseStatus":
339+
"ResponseStatus":
337340
{
338341
"ErrorCode": ""401",
339342
"Message": ""Unauthorized",

0 commit comments

Comments
 (0)