diff --git a/Common/Algorithm/Framework/Portfolio/SignalExports/Collective2SignalExport.cs b/Common/Algorithm/Framework/Portfolio/SignalExports/Collective2SignalExport.cs index b86f5946c351..c922eeeb0600 100644 --- a/Common/Algorithm/Framework/Portfolio/SignalExports/Collective2SignalExport.cs +++ b/Common/Algorithm/Framework/Portfolio/SignalExports/Collective2SignalExport.cs @@ -31,6 +31,12 @@ namespace QuantConnect.Algorithm.Framework.Portfolio.SignalExports /// public class Collective2SignalExport : BaseSignalExport { + /// + /// Hashset of symbols whose market is unknown but have already been seen by + /// this signal export manager + /// + private HashSet _unknownMarketSymbols; + /// /// API key provided by Collective2 /// @@ -86,6 +92,7 @@ public class Collective2SignalExport : BaseSignalExport /// Whether to use the white-label API instead of the general one public Collective2SignalExport(string apiKey, int systemId, bool useWhiteLabelApi = false) { + _unknownMarketSymbols = new HashSet(); _apiKey = apiKey; _systemId = systemId; Destination = new Uri(useWhiteLabelApi @@ -131,7 +138,7 @@ protected bool ConvertHoldingsToCollective2(SignalExportTargetParameters paramet { _algorithm = parameters.Algorithm; var targets = parameters.Targets; - positions = new List(); + positions = []; foreach (var target in targets) { if (target == null) @@ -140,27 +147,29 @@ protected bool ConvertHoldingsToCollective2(SignalExportTargetParameters paramet return false; } - if (!ConvertTypeOfSymbol(target.Symbol, out string typeOfSymbol)) + var securityType = GetSecurityTypeAcronym(target.Symbol.SecurityType); + if (securityType == null) { - return false; + continue; } - var symbol = _algorithm.Ticker(target.Symbol); - if (target.Symbol.SecurityType == SecurityType.Future) + var maturityMonthYear = GetMaturityMonthYear(target.Symbol); + if (maturityMonthYear?.Length == 0) { - symbol = $"@{SymbolRepresentation.GenerateFutureTicker(target.Symbol.ID.Symbol, target.Symbol.ID.Date, doubleDigitsYear: false, includeExpirationDate: false)}"; - } - else if (target.Symbol.SecurityType.IsOption()) - { - symbol = SymbolRepresentation.GenerateOptionTicker(target.Symbol); + continue; } positions.Add(new Collective2Position { - C2Symbol = new C2Symbol + ExchangeSymbol = new C2ExchangeSymbol { - FullSymbol = symbol, - SymbolType = typeOfSymbol, + Symbol = GetSymbol(target.Symbol), + Currency = parameters.Algorithm.AccountCurrency, + SecurityExchange = GetMICExchangeCode(target.Symbol), + SecurityType = securityType, + MaturityMonthYear = maturityMonthYear, + PutOrCall = GetPutOrCallValue(target.Symbol), + StrikePrice = GetStrikePrice(target.Symbol) }, Quantity = ConvertPercentageToQuantity(_algorithm, target), }); @@ -169,46 +178,6 @@ protected bool ConvertHoldingsToCollective2(SignalExportTargetParameters paramet return true; } - /// - /// Classifies a symbol type into the possible symbol types values defined - /// by Collective2 API. - /// - /// Symbol of the desired position - /// The type of the symbol according to Collective2 API - /// True if the symbol's type is supported by Collective2, false otherwise - private bool ConvertTypeOfSymbol(Symbol targetSymbol, out string typeOfSymbol) - { - switch (targetSymbol.SecurityType) - { - case SecurityType.Equity: - typeOfSymbol = "stock"; - break; - case SecurityType.Option: - typeOfSymbol = "option"; - break; - case SecurityType.Future: - typeOfSymbol = "future"; - break; - case SecurityType.Forex: - typeOfSymbol = "forex"; - break; - case SecurityType.IndexOption: - typeOfSymbol = "option"; - break; - default: - typeOfSymbol = "NotImplemented"; - break; - } - - if (typeOfSymbol == "NotImplemented") - { - _algorithm.Error($"{targetSymbol.SecurityType} security type is not supported by Collective2."); - return false; - } - - return true; - } - /// /// Converts a given percentage of a position into the number of shares of it /// @@ -332,6 +301,138 @@ private class DesiredPositionResponse public List CanceledSignals { get; set; } = new List(); } + /// + /// Returns the given symbol in the expected C2 format + /// + private string GetSymbol(Symbol symbol) + { + if (CurrencyPairUtil.TryDecomposeCurrencyPair(symbol, out var baseCurrency, out var quoteCurrency)) + { + return $"{baseCurrency}/{quoteCurrency}"; + } + else if (symbol.SecurityType.IsOption()) + { + return symbol.Underlying.Value; + } + else + { + return symbol.ID.Symbol; + } + } + + private string GetMICExchangeCode(Symbol symbol) + { + if (_unknownMarketSymbols.Contains(symbol.Value) || symbol.SecurityType == SecurityType.Equity || symbol.SecurityType.IsOption()) + { + return "DEFAULT"; + } + + switch (symbol.ID.Market) + { + case "india": + return "XNSE"; + case "hkfe": + return "XHKF"; + case "nyseliffe": + return "XNLI"; + case "eurex": + return "XEUR"; + case "ice": + return "IEPA"; + case "cboe": + return "XCBO"; + case "cfe": + return "XCBF"; + case "cbot": + return "XCBT"; + case "comex": + return "XCEC"; + case "nymex": + return "XNYM"; + case "sgx": + return "XSES"; + case "fxcm": + return symbol.ID.Market.ToUpper(); + case "ose": + case "cme": + return "X" + symbol.ID.Market.ToUpper(); + default: + _unknownMarketSymbols.Add(symbol.Value); + _algorithm.Debug($"The market of the symbol {symbol.Value} was unexpected: {symbol.ID.Market}. Using 'DEFAULT' as market"); + return "DEFAULT"; + } + } + + /// + /// Returns the given security type in the format C2 expects + /// + private string GetSecurityTypeAcronym(SecurityType securityType) + { + switch (securityType) + { + case SecurityType.Equity: + return "CS"; + case SecurityType.Future: + return "FUT"; + case SecurityType.Option: + case SecurityType.IndexOption: + return "OPT"; + case SecurityType.Forex: + return "FOR"; + default: + _algorithm.Error($"Unexpected security type found: {securityType}. Collective2 just accepts: Equity, Future, Option, Index Option and Stock"); + return null; + } + } + + /// + /// Returns the expiration date in the format C2 expects + /// + private string GetMaturityMonthYear(Symbol symbol) + { + var delistingDate = symbol.GetDelistingDate(); + if (delistingDate == Time.EndOfTime) // The given symbol is equity or forex + { + return null; + } + + if (delistingDate < _algorithm.Securities[symbol].LocalTime) // The given symbol has already expired + { + _algorithm.Error($"Instrument {symbol} has already expired. Its delisting date was: {delistingDate}. This signal won't be sent to Collective2."); + return string.Empty; + } + + return $"{delistingDate:yyyyMMdd}"; + } + + private int? GetPutOrCallValue(Symbol symbol) + { + if (symbol.SecurityType.IsOption()) + { + switch (symbol.ID.OptionRight) + { + case OptionRight.Put: + return 0; + case OptionRight.Call: + return 1; + } + } + + return null; + } + + private decimal? GetStrikePrice(Symbol symbol) + { + if (symbol.SecurityType.IsOption()) + { + return symbol.ID.StrikePrice; + } + else + { + return null; + } + } + /// /// The C2 ResponseStatus object /// @@ -393,34 +494,72 @@ protected class Collective2Position /// /// Position symbol /// - [JsonProperty(PropertyName = "C2Symbol")] - public C2Symbol C2Symbol { get; set; } + [JsonProperty(PropertyName = "exchangeSymbol")] + public C2ExchangeSymbol ExchangeSymbol { get; set; } /// /// Number of shares/contracts of the given symbol. Positive quantites are long positions /// and negative short positions. /// - [JsonProperty(PropertyName = "Quantity")] + [JsonProperty(PropertyName = "quantity")] public decimal Quantity { get; set; } // number of shares, not % of the portfolio } /// /// The Collective2 symbol /// - protected class C2Symbol + protected class C2ExchangeSymbol { /// - /// The The full native C2 symbol e.g. BSRR2121Q22.5 + /// The exchange root symbol e.g. AAPL + /// + [JsonProperty(PropertyName = "symbol")] + public string Symbol { get; set; } + + /// + /// The 3-character ISO instrument currency. E.g. 'USD' + /// + [JsonProperty(PropertyName = "currency")] + public string Currency { get; set; } + + /// + /// The MIC Exchange code e.g. DEFAULT (for stocks & options), + /// XCME, XEUR, XICE, XLIF, XNYB, XNYM, XASX, XCBF, XCBT, XCEC, + /// XKBT, XSES. See details at http://www.iso15022.org/MIC/homepageMIC.htm /// - [JsonProperty(PropertyName = "FullSymbol")] - public string FullSymbol { get; set; } + [JsonProperty(PropertyName = "securityExchange")] + public string SecurityExchange { get; set; } /// - /// The type of instrument. e.g. 'stock', 'option', 'future', 'forex' + /// The SecurityType e.g. 'CS'(Common Stock), 'FUT' (Future), 'OPT' (Option), 'FOR' (Forex) + /// + [JsonProperty(PropertyName = "securityType")] + public string SecurityType { get; set; } + + /// + /// The MaturityMonthYear e.g. '202103' (March 2021), or if the contract requires a day: '20210521' (May 21, 2021) + /// + [JsonProperty(PropertyName = "maturityMonthYear")] + public string MaturityMonthYear { get; set; } + + /// + /// The Option PutOrCall e.g. 0 = Put, 1 = Call + /// + [JsonProperty(PropertyName = "putOrCall")] + public int? PutOrCall { get; set; } + + /// + /// The ISO Option Strike Price. Zero means none + /// + [JsonProperty(PropertyName = "strikePrice")] + public decimal? StrikePrice { get; set; } + + /// + /// The multiplier to apply to the Exchange price to get the C2-formatted price. Default is 1 /// - [JsonProperty(PropertyName = "SymbolType")] - public string SymbolType { get; set; } + [JsonProperty(PropertyName = "priceMultiplier")] + public decimal PriceMultiplier { get; set; } = 1; } } } diff --git a/Tests/Algorithm/Framework/Portfolio/SignalExportTargetTests.cs b/Tests/Algorithm/Framework/Portfolio/SignalExportTargetTests.cs index d6ba4f6c181a..8d6d65e744c9 100644 --- a/Tests/Algorithm/Framework/Portfolio/SignalExportTargetTests.cs +++ b/Tests/Algorithm/Framework/Portfolio/SignalExportTargetTests.cs @@ -30,38 +30,49 @@ namespace QuantConnect.Tests.Algorithm.Framework.Portfolio [TestFixture] public class SignalExportTargetTests { - [Test] - public void SendsTargetsToCollective2Appropiately() + [TestCaseSource(nameof(SendsTargetsToCollective2AppropiatelyTestCases))] + public void SendsTargetsToCollective2Appropiately(string currency, Symbol symbol, decimal quantity, string expectedMessage) { - var symbols = new List() - { - Symbols.SPY, - Symbols.EURUSD, - Symbols.Future_ESZ18_Dec2018, - Symbols.SPY_C_192_Feb19_2016 - }; - - var targetList = new List() - { - new PortfolioTarget(Symbols.SPY, (decimal)0.2), - new PortfolioTarget(Symbols.EURUSD, (decimal)0.3), - new PortfolioTarget(Symbols.Future_ESZ18_Dec2018, (decimal)0.2), - new PortfolioTarget(Symbols.SPY_C_192_Feb19_2016, (decimal)0.3) - }; + var targetList = new List() { new(symbol, quantity) }; var algorithm = new AlgorithmStub(); - AddSymbols(symbols, algorithm); + algorithm.SetDateTime(new DateTime(2016, 02, 16, 11, 53, 30)); + algorithm.Portfolio.SetAccountCurrency(currency); + var security = algorithm.AddSecurity(symbol); + security.SetMarketPrice(new Tick { Value = 100 }); + algorithm.Portfolio.SetCash(50000); using var manager = new Collective2SignalExportHandler("", 0); var message = manager.GetMessageSent(new SignalExportTargetParameters { Targets = targetList, Algorithm = algorithm }); - var expectedMessage = @"{""StrategyId"":0,""Positions"":[{""C2Symbol"":{""FullSymbol"":""SPY"",""SymbolType"":""stock""},""Quantity"":99.0},{""C2Symbol"":{""FullSymbol"":""EURUSD"",""SymbolType"":""forex""},""Quantity"":149.0},{""C2Symbol"":{""FullSymbol"":""@ESZ8"",""SymbolType"":""future""},""Quantity"":2.0},{""C2Symbol"":{""FullSymbol"":""SPY1619B192"",""SymbolType"":""option""},""Quantity"":1.0}]}"; - Assert.AreEqual(expectedMessage, message); } + [Test] + public void Collective2SignalExportManagerDoesNotLogMoreThanOnceWhenUnknownMarket() + { + var targetList = new List() { new(Symbols.EURUSD, 1) }; + + var algorithm = new AlgorithmStub(); + algorithm.SetDateTime(new DateTime(2016, 02, 16, 11, 53, 30)); + algorithm.Portfolio.SetAccountCurrency("USD"); + var security = algorithm.AddSecurity(Symbols.EURUSD); + security.SetMarketPrice(new Tick { Value = 100 }); + + algorithm.Portfolio.SetCash(50000); + + using var manager = new Collective2SignalExportHandler("", 0); + + for (int count = 0; count < 100; count++) + { + manager.GetMessageSent(new SignalExportTargetParameters { Targets = targetList, Algorithm = algorithm }); + } + + Assert.AreEqual(1, algorithm.DebugMessages.Count); + } + [Test] public void Collective2ConvertsPercentageToQuantityAppropiately() { @@ -388,6 +399,51 @@ public void SignalExportManagerReturnsFalseWhenNegativeTotalPortfolioValue() Assert.IsFalse(signalExportManagerHandler.GetPortfolioTargets(out _)); } + private static object[] SendsTargetsToCollective2AppropiatelyTestCases = + { + new object[] { "USD", Symbols.SPY, 0.2m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""SPY"",""currency"":""USD"",""securityExchange"":""DEFAULT"",""securityType"":""CS"",""maturityMonthYear"":null,""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":99.0}]}" }, + new object[] { "USD", Symbols.EURUSD, 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""EUR/USD"",""currency"":""USD"",""securityExchange"":""DEFAULT"",""securityType"":""FOR"",""maturityMonthYear"":null,""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "USD", Symbols.EURGBP, 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""EUR/GBP"",""currency"":""USD"",""securityExchange"":""DEFAULT"",""securityType"":""FOR"",""maturityMonthYear"":null,""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "USD", Symbols.GBPJPY, 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""GBP/JPY"",""currency"":""USD"",""securityExchange"":""DEFAULT"",""securityType"":""FOR"",""maturityMonthYear"":null,""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "USD", Symbols.GBPUSD, 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""GBP/USD"",""currency"":""USD"",""securityExchange"":""DEFAULT"",""securityType"":""FOR"",""maturityMonthYear"":null,""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "USD", Symbols.USDJPY, 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""USD/JPY"",""currency"":""USD"",""securityExchange"":""DEFAULT"",""securityType"":""FOR"",""maturityMonthYear"":null,""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "USD", Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 192m, new DateTime(2016, 02, 15)), 0.2m, @"{""StrategyId"":0,""Positions"":[]}" }, + new object[] { "USD", Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 192m, new DateTime(2056, 02, 19)), 0.2m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""SPY"",""currency"":""USD"",""securityExchange"":""DEFAULT"",""securityType"":""OPT"",""maturityMonthYear"":""20560218"",""putOrCall"":1,""strikePrice"":192.0,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "USD", Symbols.CreateOptionSymbol("SPY", OptionRight.Put, 192m, new DateTime(2056, 02, 19)), 0.2m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""SPY"",""currency"":""USD"",""securityExchange"":""DEFAULT"",""securityType"":""OPT"",""maturityMonthYear"":""20560218"",""putOrCall"":0,""strikePrice"":192.0,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "USD", Symbol.Create("EURUSD", SecurityType.Forex, Market.FXCM), 0.2m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""EUR/USD"",""currency"":""USD"",""securityExchange"":""FXCM"",""securityType"":""FOR"",""maturityMonthYear"":null,""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "USD", Symbol.Create("NQX", SecurityType.IndexOption, Market.USA), 0.2m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""NQX"",""currency"":""USD"",""securityExchange"":""DEFAULT"",""securityType"":""OPT"",""maturityMonthYear"":null,""putOrCall"":1,""strikePrice"":0.0,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "USD", Symbol.CreateFuture("NIFTY", Market.India, new DateTime(2056, 02, 19)), 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""NIFTY"",""currency"":""USD"",""securityExchange"":""XNSE"",""securityType"":""FUT"",""maturityMonthYear"":""20560219"",""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "USD", Symbol.CreateFuture("HSI", Market.HKFE, new DateTime(2056, 02, 19)), 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""HSI"",""currency"":""USD"",""securityExchange"":""XHKF"",""securityType"":""FUT"",""maturityMonthYear"":""20560219"",""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "USD", Symbol.CreateFuture("ZG", Market.NYSELIFFE, new DateTime(2056, 02, 19)), 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""ZG"",""currency"":""USD"",""securityExchange"":""XNLI"",""securityType"":""FUT"",""maturityMonthYear"":""20560219"",""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "USD", Symbol.CreateFuture("FESX", Market.EUREX, new DateTime(2056, 02, 19)), 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""FESX"",""currency"":""USD"",""securityExchange"":""XEUR"",""securityType"":""FUT"",""maturityMonthYear"":""20560219"",""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "USD", Symbol.CreateFuture("KC", Market.ICE, new DateTime(2056, 02, 19)), 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""KC"",""currency"":""USD"",""securityExchange"":""IEPA"",""securityType"":""FUT"",""maturityMonthYear"":""20560219"",""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "USD", Symbol.CreateFuture("VIX", Market.CFE, new DateTime(2056, 02, 19)), 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""VIX"",""currency"":""USD"",""securityExchange"":""XCBF"",""securityType"":""FUT"",""maturityMonthYear"":""20560219"",""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "USD", Symbol.CreateFuture("ZC", Market.CBOT, new DateTime(2056, 02, 19)), 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""ZC"",""currency"":""USD"",""securityExchange"":""XCBT"",""securityType"":""FUT"",""maturityMonthYear"":""20560219"",""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "USD", Symbol.CreateFuture("GC", Market.COMEX, new DateTime(2056, 02, 19)), 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""GC"",""currency"":""USD"",""securityExchange"":""XCEC"",""securityType"":""FUT"",""maturityMonthYear"":""20560219"",""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "USD", Symbol.CreateFuture("CL", Market.NYMEX, new DateTime(2056, 02, 19)), 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""CL"",""currency"":""USD"",""securityExchange"":""XNYM"",""securityType"":""FUT"",""maturityMonthYear"":""20560219"",""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "USD", Symbol.CreateFuture("NK", Market.SGX, new DateTime(2056, 02, 19)), 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""NK"",""currency"":""USD"",""securityExchange"":""XSES"",""securityType"":""FUT"",""maturityMonthYear"":""20560219"",""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "EUR", Symbols.SPY, 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""SPY"",""currency"":""EUR"",""securityExchange"":""DEFAULT"",""securityType"":""CS"",""maturityMonthYear"":null,""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "EUR", Symbols.EURUSD, 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""EUR/USD"",""currency"":""EUR"",""securityExchange"":""DEFAULT"",""securityType"":""FOR"",""maturityMonthYear"":null,""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "EUR", Symbols.EURGBP, 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""EUR/GBP"",""currency"":""EUR"",""securityExchange"":""DEFAULT"",""securityType"":""FOR"",""maturityMonthYear"":null,""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "EUR", Symbols.GBPJPY, 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""GBP/JPY"",""currency"":""EUR"",""securityExchange"":""DEFAULT"",""securityType"":""FOR"",""maturityMonthYear"":null,""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "EUR", Symbols.GBPUSD, 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""GBP/USD"",""currency"":""EUR"",""securityExchange"":""DEFAULT"",""securityType"":""FOR"",""maturityMonthYear"":null,""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "EUR", Symbols.USDJPY, 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""USD/JPY"",""currency"":""EUR"",""securityExchange"":""DEFAULT"",""securityType"":""FOR"",""maturityMonthYear"":null,""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "EUR", Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 192m, new DateTime(2056, 02, 19)), 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""SPY"",""currency"":""EUR"",""securityExchange"":""DEFAULT"",""securityType"":""OPT"",""maturityMonthYear"":""20560218"",""putOrCall"":1,""strikePrice"":192.0,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "EUR", Symbols.CreateOptionSymbol("SPY", OptionRight.Put, 192m, new DateTime(2056, 02, 19)), 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""SPY"",""currency"":""EUR"",""securityExchange"":""DEFAULT"",""securityType"":""OPT"",""maturityMonthYear"":""20560218"",""putOrCall"":0,""strikePrice"":192.0,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "EUR", Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 192m, new DateTime(2016, 02, 15)), 0.2m, @"{""StrategyId"":0,""Positions"":[]}" }, + new object[] { "EUR", Symbol.Create("EURUSD", SecurityType.Forex, Market.FXCM), 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""EUR/USD"",""currency"":""EUR"",""securityExchange"":""FXCM"",""securityType"":""FOR"",""maturityMonthYear"":null,""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "EUR", Symbol.CreateFuture("NIFTY", Market.India, new DateTime(2056, 02, 19)), 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""NIFTY"",""currency"":""EUR"",""securityExchange"":""XNSE"",""securityType"":""FUT"",""maturityMonthYear"":""20560219"",""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "EUR", Symbol.CreateFuture("HSI", Market.HKFE, new DateTime(2056, 02, 19)), 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""HSI"",""currency"":""EUR"",""securityExchange"":""XHKF"",""securityType"":""FUT"",""maturityMonthYear"":""20560219"",""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "EUR", Symbol.CreateFuture("ZG", Market.NYSELIFFE, new DateTime(2056, 02, 19)), 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""ZG"",""currency"":""EUR"",""securityExchange"":""XNLI"",""securityType"":""FUT"",""maturityMonthYear"":""20560219"",""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "EUR", Symbol.CreateFuture("FESX", Market.EUREX, new DateTime(2056, 02, 19)), 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""FESX"",""currency"":""EUR"",""securityExchange"":""XEUR"",""securityType"":""FUT"",""maturityMonthYear"":""20560219"",""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "EUR", Symbol.CreateFuture("KC", Market.ICE, new DateTime(2056, 02, 19)), 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""KC"",""currency"":""EUR"",""securityExchange"":""IEPA"",""securityType"":""FUT"",""maturityMonthYear"":""20560219"",""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "EUR", Symbol.CreateFuture("VIX", Market.CFE, new DateTime(2056, 02, 19)), 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""VIX"",""currency"":""EUR"",""securityExchange"":""XCBF"",""securityType"":""FUT"",""maturityMonthYear"":""20560219"",""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "EUR", Symbol.CreateFuture("ZC", Market.CBOT, new DateTime(2056, 02, 19)), 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""ZC"",""currency"":""EUR"",""securityExchange"":""XCBT"",""securityType"":""FUT"",""maturityMonthYear"":""20560219"",""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "EUR", Symbol.CreateFuture("GC", Market.COMEX, new DateTime(2056, 02, 19)), 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""GC"",""currency"":""EUR"",""securityExchange"":""XCEC"",""securityType"":""FUT"",""maturityMonthYear"":""20560219"",""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "EUR", Symbol.CreateFuture("CL", Market.NYMEX, new DateTime(2056, 02, 19)), 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""CL"",""currency"":""EUR"",""securityExchange"":""XNYM"",""securityType"":""FUT"",""maturityMonthYear"":""20560219"",""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + new object[] { "EUR", Symbol.CreateFuture("NK", Market.SGX, new DateTime(2056, 02, 19)), 0m, @"{""StrategyId"":0,""Positions"":[{""exchangeSymbol"":{""symbol"":""NK"",""currency"":""EUR"",""securityExchange"":""XSES"",""securityType"":""FUT"",""maturityMonthYear"":""20560219"",""putOrCall"":null,""strikePrice"":null,""priceMultiplier"":1.0},""quantity"":0.0}]}" }, + }; + private static void AddSymbols(List symbols, QCAlgorithm algorithm) { algorithm.SetDateTime(new DateTime(2016, 02, 16, 11, 53, 30));