Skip to content

Commit

Permalink
Support Collective2 white-label API (#8536)
Browse files Browse the repository at this point in the history
* Support Collective2 white-labe api usage

* Make Collective2SignalExport Destination public and assignable

* Minor comment change
  • Loading branch information
jhonabreul authored Jan 15, 2025
1 parent c35d6ee commit 41f9d1b
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,13 @@ public class Collective2SignalExportDemonstrationAlgorithm : QCAlgorithm, IRegre
private bool _firstCall = true;

private PortfolioTarget[] _targets = new PortfolioTarget[4];

/// <summary>
/// Symbols accepted by Collective2. Collective2 accepts stock,
/// future, forex and US stock option symbols
/// </summary>
private List<Symbol> _symbols = new()
{
{
QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA, null, null),
QuantConnect.Symbol.Create("EURUSD", SecurityType.Forex, Market.Oanda, null, null),
QuantConnect.Symbol.CreateFuture("ES", Market.CME, new DateTime(2023, 12, 15), null),
Expand Down Expand Up @@ -95,15 +95,19 @@ public override void Initialize()
// Initialize this flag, to check when the ema indicators crosses between themselves
_emaFastIsNotSet = true;

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

SetWarmUp(100);
}

/// <summary>
/// Reduce the quantity of holdings for SPY or increase it, depending the case,
/// when the EMA's indicators crosses between themselves, then send a signal to
/// Reduce the quantity of holdings for SPY or increase it, depending the case,
/// when the EMA's indicators crosses between themselves, then send a signal to
/// Collective2 API
/// </summary>
/// <param name="slice"></param>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ def initialize(self):
# Collective2 System ID: This value is found beside the system's name (strategy's name) on the main system page
self.collective2_system_id = 0

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

self.first_call = True
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,6 @@ public class Collective2SignalExport : BaseSignalExport
/// </summary>
private readonly int _systemId;

/// <summary>
/// Collective2 API endpoint
/// </summary>
private readonly Uri _destination;

/// <summary>
/// Algorithm being ran
/// </summary>
Expand All @@ -56,6 +51,11 @@ public class Collective2SignalExport : BaseSignalExport
/// </summary>
private bool _isZeroPriceWarningPrinted;

/// <summary>
/// Collective2 API endpoint
/// </summary>
public Uri Destination { get; set; }

/// <summary>
/// The name of this signal export
/// </summary>
Expand Down Expand Up @@ -83,18 +83,21 @@ public class Collective2SignalExport : BaseSignalExport
/// </summary>
/// <param name="apiKey">API key provided by Collective2</param>
/// <param name="systemId">Trading system's ID number</param>
public Collective2SignalExport(string apiKey, int systemId)
/// <param name="useWhiteLabelApi">Whether to use the white-label API instead of the general one</param>
public Collective2SignalExport(string apiKey, int systemId, bool useWhiteLabelApi = false)
{
_apiKey = apiKey;
_systemId = systemId;
_destination = new Uri("https://api4-general.collective2.com/Strategies/SetDesiredPositions");
Destination = new Uri(useWhiteLabelApi
? "https://api4-wl.collective2.com/Strategies/SetDesiredPositions"
: "https://api4-general.collective2.com/Strategies/SetDesiredPositions");
}

/// <summary>
/// Creates a JSON message with the desired positions using the expected
/// Collective2 API format and then sends it
/// </summary>
/// <param name="parameters">A list of holdings from the portfolio
/// <param name="parameters">A list of holdings from the portfolio
/// expected to be sent to Collective2 API and the algorithm being ran</param>
/// <returns>True if the positions were sent correctly and Collective2 sent no errors, false otherwise</returns>
public override bool Send(SignalExportTargetParameters parameters)
Expand All @@ -120,7 +123,7 @@ public override bool Send(SignalExportTargetParameters parameters)
/// <summary>
/// Converts a list of targets to a list of Collective2 positions
/// </summary>
/// <param name="parameters">A list of targets from the portfolio
/// <param name="parameters">A list of targets from the portfolio
/// expected to be sent to Collective2 API and the algorithm being ran</param>
/// <param name="positions">A list of Collective2 positions</param>
/// <returns>True if the given targets could be converted to a Collective2Position list, false otherwise</returns>
Expand Down Expand Up @@ -266,7 +269,7 @@ private bool SendPositions(string message)
HttpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _apiKey);

//Send the message
using HttpResponseMessage response = HttpClient.PostAsync(_destination, httpMessage).Result;
using HttpResponseMessage response = HttpClient.PostAsync(Destination, httpMessage).Result;

//Parse it
var responseObject = response.Content.ReadFromJsonAsync<C2Response>().Result;
Expand Down Expand Up @@ -333,7 +336,7 @@ private class ResponseStatus
{
/* Example:
"ResponseStatus":
"ResponseStatus":
{
"ErrorCode": ""401",
"Message": ""Unauthorized",
Expand Down

0 comments on commit 41f9d1b

Please sign in to comment.