Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Collective2 white-label API #8536

Merged
merged 3 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading