17 using System.Collections.Generic;
18 using System.Globalization;
20 using System.Reflection;
56 public List<Exception>
Errors {
get;
set; }
87 Errors =
new List<Exception>();
105 var complete = loader.TryCreateAlgorithmInstanceWithIsolator(assemblyPath, algorithmNodePacket.
RamAllocation, out algorithm, out error);
106 if (!complete)
throw new AlgorithmSetupException($
"During the algorithm initialization, the following exception has occurred: {error}");
123 throw new ArgumentException(
"BrokerageSetupHandler.CreateBrokerage requires a live node packet");
126 Log.
Trace($
"BrokerageSetupHandler.CreateBrokerage(): creating brokerage '{liveJob.Brokerage}'");
132 PreloadDataQueueHandler(liveJob, uninitializedAlgorithm, factory);
135 var brokerage = _factory.
CreateBrokerage(liveJob, uninitializedAlgorithm);
153 AddInitializationError(
"BrokerageSetupHandler requires a LiveNodePacket");
157 algorithm.Name = liveJob.GetAlgorithmName();
160 if (
string.IsNullOrWhiteSpace(liveJob.Brokerage))
162 AddInitializationError(
"A brokerage must be specified");
169 EventHandler<BrokerageMessageEvent> brokerageOnMessage = (sender, args) =>
173 AddInitializationError($
"Brokerage Error Code: {args.Code} - {args.Message}");
182 brokerage.Message += brokerageOnMessage;
184 Log.
Trace(
"BrokerageSetupHandler.Setup(): Connecting to brokerage...");
190 catch (Exception err)
193 AddInitializationError(
194 $
"Error connecting to brokerage: {err.Message}. " +
195 "This may be caused by incorrect login credentials or an unsupported account type.", err);
199 if (!brokerage.IsConnected)
202 AddInitializationError(
"Unable to connect to brokerage.");
206 var message = $
"{brokerage.Name} account base currency: {brokerage.AccountBaseCurrency ?? algorithm.AccountCurrency}";
209 var accountCurrency = brokerage.AccountBaseCurrency;
213 message +=
". Allocation limited, will use 'USD' account currency";
216 Log.
Trace($
"BrokerageSetupHandler.Setup(): {message}");
218 algorithm.Debug(message);
219 if (accountCurrency !=
null && accountCurrency != algorithm.AccountCurrency)
221 algorithm.SetAccountCurrency(accountCurrency);
224 Log.
Trace(
"BrokerageSetupHandler.Setup(): Initializing algorithm...");
229 var controls = liveJob.Controls;
231 var initializeComplete = isolator.ExecuteWithTimeLimit(TimeSpan.FromSeconds(300), () =>
236 algorithm.SetBrokerageModel(_factory.GetBrokerageModel(algorithm.Transactions));
239 algorithm.Portfolio.MarginCallModel = MarginCallModel.Null;
242 algorithm.SetParameters(liveJob.Parameters);
243 algorithm.SetAvailableDataTypes(BaseSetupHandler.GetConfiguredDataFeeds());
246 algorithm.SetAlgorithmMode(liveJob.AlgorithmMode);
249 algorithm.SetDateTime(DateTime.UtcNow);
252 algorithm.Schedule.SetEventSchedule(parameters.RealTimeHandler);
254 var optionChainProvider = Composer.Instance.GetPart<IOptionChainProvider>();
255 if (optionChainProvider == null)
257 optionChainProvider = new CachingOptionChainProvider(new LiveOptionChainProvider(parameters.DataCacheProvider, parameters.MapFileProvider));
258 Composer.Instance.AddPart(optionChainProvider);
261 algorithm.SetOptionChainProvider(optionChainProvider);
263 var futureChainProvider = Composer.Instance.GetPart<IFutureChainProvider>();
264 if (futureChainProvider == null)
266 futureChainProvider = new CachingFutureChainProvider(new LiveFutureChainProvider(parameters.DataCacheProvider));
267 Composer.Instance.AddPart(futureChainProvider);
270 algorithm.SetFutureChainProvider(futureChainProvider);
273 algorithm.Initialize();
275 if (liveJob.Brokerage !=
"PaperBrokerage")
278 foreach (var kvp in algorithm.Portfolio.CashBook)
280 kvp.Value.SetAmount(0);
284 catch (Exception err)
286 AddInitializationError(err.ToString(), err);
288 }, controls.RamAllocation,
289 sleepIntervalMillis: 100);
297 if (!initializeComplete)
299 AddInitializationError(
"Initialization timed out.");
303 if (!LoadCashBalance(brokerage, algorithm))
320 algorithm.PostInitialize();
324 if (algorithm.Portfolio.TotalPortfolioValue == 0)
326 algorithm.Debug(
"Warning: No cash balances or holdings were found in the brokerage account.");
329 string maxCashLimitStr;
332 var maxCashLimit = decimal.Parse(maxCashLimitStr, NumberStyles.Any, CultureInfo.InvariantCulture);
335 if (algorithm.Portfolio.TotalPortfolioValue > (maxCashLimit + 10000m))
337 var exceptionMessage = $
"TotalPortfolioValue '{algorithm.Portfolio.TotalPortfolioValue}' exceeds allocation limit '{maxCashLimit}'";
338 algorithm.Debug(exceptionMessage);
339 throw new ArgumentException(exceptionMessage);
347 catch (Exception err)
349 AddInitializationError(err.ToString(), err);
353 if (brokerage !=
null)
355 brokerage.Message -= brokerageOnMessage;
364 Log.
Trace(
"BrokerageSetupHandler.Setup(): Fetching cash balance from brokerage...");
369 foreach (var cash
in cashBalance)
371 Log.
Trace($
"BrokerageSetupHandler.Setup(): Setting {cash.Currency} cash to {cash.Amount}");
376 catch (Exception err)
379 AddInitializationError(
"Error getting cash balance from brokerage: " + err.Message, err);
390 Log.
Trace(
"BrokerageSetupHandler.Setup(): Fetching open orders from brokerage...");
395 catch (Exception err)
398 AddInitializationError(
"Error getting open orders from brokerage: " + err.Message, err);
402 Log.
Trace(
"BrokerageSetupHandler.Setup(): Fetching holdings from brokerage...");
405 var utcNow = DateTime.UtcNow;
411 foreach (var holding
in holdings.OrderByDescending(x => x.Type))
413 Log.
Trace(
"BrokerageSetupHandler.Setup(): Has existing holding: " + holding);
417 if (!GetOrAddUnrequestedSecurity(algorithm, holding.
Symbol, holding.Type, out security))
422 var exchangeTime = utcNow.ConvertFromUtc(security.Exchange.TimeZone);
426 if (holding.MarketPrice == 0)
432 if (holding.MarketPrice != 0)
434 security.SetMarketPrice(
new TradeBar
437 Open = holding.MarketPrice,
438 High = holding.MarketPrice,
439 Low = holding.MarketPrice,
440 Close = holding.MarketPrice,
448 catch (Exception err)
451 AddInitializationError(
"Error getting account holdings from brokerage: " + err.Message, err);
460 return algorithm.GetOrAddUnrequestedSecurity(symbol, out security,
461 onError: (supportedSecurityTypes) => AddInitializationError(
462 "Found unsupported security type in existing brokerage holdings: " + securityType +
". " +
463 "QuantConnect currently supports the following security types: " +
string.Join(
",", supportedSecurityTypes)));
479 foreach (var order
in openOrders.OrderByDescending(x => x.SecurityType))
483 if (!GetOrAddUnrequestedSecurity(algorithm, order.
Symbol, order.
SecurityType, out security))
488 transactionHandler.AddOpenOrder(order, algorithm);
491 Log.
Trace($
"BrokerageSetupHandler.Setup(): Has open order: {order}");
492 resultHandler.DebugMessage($
"BrokerageSetupHandler.Setup(): Open order detected. Creating order tickets for open order {order.Symbol.Value} with quantity {order.Quantity}. Beware that this order ticket may not accurately reflect the quantity of the order if the open order is partially filled.");
501 private void AddInitializationError(
string message, Exception inner =
null)
503 Errors.Add(
new AlgorithmSetupException(
"During the algorithm initialization, the following exception has occurred: " + message, inner));
512 _factory?.DisposeSafely();
514 if (_dataQueueHandlerBrokerage !=
null)
520 _dataQueueHandlerBrokerage.DisposeSafely();
525 if (dataQueueHandler !=
null)
527 Log.
Trace($
"BrokerageSetupHandler.Setup(): Found data queue handler to dispose: {dataQueueHandler.GetType()}");
528 dataQueueHandler.DisposeSafely();
532 Log.
Trace(
"BrokerageSetupHandler.Setup(): did not find any data queue handler to dispose");
540 var dataQueueHandlerType = Assembly.GetAssembly(typeof(
Brokerage))
543 x.FullName !=
null &&
547 if (dataQueueHandlerType !=
null)
552 if (attribute.Type != factory.GetType())
554 var brokerageFactory = (
BrokerageFactory)Activator.CreateInstance(attribute.Type);
557 foreach (var kvp
in brokerageFactory.BrokerageData)
566 _dataQueueHandlerBrokerage = brokerageFactory.CreateBrokerage(liveJob, algorithm);
569 _dataQueueHandlerBrokerage.
Connect();