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 var baseOptionChainProvider = new LiveOptionChainProvider();
258 baseOptionChainProvider.Initialize(new(parameters.MapFileProvider, algorithm.HistoryProvider));
259 optionChainProvider = new CachingOptionChainProvider(baseOptionChainProvider);
260 Composer.Instance.AddPart(optionChainProvider);
263 algorithm.SetOptionChainProvider(optionChainProvider);
265 var futureChainProvider = Composer.Instance.GetPart<IFutureChainProvider>();
266 if (futureChainProvider == null)
268 var baseFutureChainProvider = new LiveFutureChainProvider();
269 baseFutureChainProvider.Initialize(new(parameters.MapFileProvider, algorithm.HistoryProvider));
270 futureChainProvider = new CachingFutureChainProvider(baseFutureChainProvider);
271 Composer.Instance.AddPart(futureChainProvider);
274 algorithm.SetFutureChainProvider(futureChainProvider);
277 algorithm.Initialize();
279 if (liveJob.Brokerage !=
"PaperBrokerage")
282 foreach (var kvp in algorithm.Portfolio.CashBook)
284 kvp.Value.SetAmount(0);
288 catch (Exception err)
290 AddInitializationError(err.ToString(), err);
292 }, controls.RamAllocation,
293 sleepIntervalMillis: 100);
301 if (!initializeComplete)
303 AddInitializationError(
"Initialization timed out.");
307 if (!LoadCashBalance(brokerage, algorithm))
324 algorithm.PostInitialize();
328 if (algorithm.Portfolio.TotalPortfolioValue == 0)
330 algorithm.Debug(
"Warning: No cash balances or holdings were found in the brokerage account.");
333 string maxCashLimitStr;
336 var maxCashLimit = decimal.Parse(maxCashLimitStr, NumberStyles.Any, CultureInfo.InvariantCulture);
339 if (algorithm.Portfolio.TotalPortfolioValue > (maxCashLimit + 10000m))
341 var exceptionMessage = $
"TotalPortfolioValue '{algorithm.Portfolio.TotalPortfolioValue}' exceeds allocation limit '{maxCashLimit}'";
342 algorithm.Debug(exceptionMessage);
343 throw new ArgumentException(exceptionMessage);
351 catch (Exception err)
353 AddInitializationError(err.ToString(), err);
357 if (brokerage !=
null)
359 brokerage.Message -= brokerageOnMessage;
368 Log.
Trace(
"BrokerageSetupHandler.Setup(): Fetching cash balance from brokerage...");
373 foreach (var cash
in cashBalance)
375 Log.
Trace($
"BrokerageSetupHandler.Setup(): Setting {cash.Currency} cash to {cash.Amount}");
380 catch (Exception err)
383 AddInitializationError(
"Error getting cash balance from brokerage: " + err.Message, err);
394 Log.
Trace(
"BrokerageSetupHandler.Setup(): Fetching open orders from brokerage...");
399 catch (Exception err)
402 AddInitializationError(
"Error getting open orders from brokerage: " + err.Message, err);
406 Log.
Trace(
"BrokerageSetupHandler.Setup(): Fetching holdings from brokerage...");
409 var utcNow = DateTime.UtcNow;
415 foreach (var holding
in holdings.OrderByDescending(x => x.Type))
417 Log.
Trace(
"BrokerageSetupHandler.Setup(): Has existing holding: " + holding);
421 if (!GetOrAddUnrequestedSecurity(algorithm, holding.
Symbol, holding.Type, out security))
426 var exchangeTime = utcNow.ConvertFromUtc(security.Exchange.TimeZone);
430 if (holding.MarketPrice == 0)
436 if (holding.MarketPrice != 0)
438 security.SetMarketPrice(
new TradeBar
441 Open = holding.MarketPrice,
442 High = holding.MarketPrice,
443 Low = holding.MarketPrice,
444 Close = holding.MarketPrice,
452 catch (Exception err)
455 AddInitializationError(
"Error getting account holdings from brokerage: " + err.Message, err);
464 return algorithm.GetOrAddUnrequestedSecurity(symbol, out security,
465 onError: (supportedSecurityTypes) => AddInitializationError(
466 "Found unsupported security type in existing brokerage holdings: " + securityType +
". " +
467 "QuantConnect currently supports the following security types: " +
string.Join(
",", supportedSecurityTypes)));
483 foreach (var order
in openOrders.OrderByDescending(x => x.SecurityType))
487 if (!GetOrAddUnrequestedSecurity(algorithm, order.
Symbol, order.
SecurityType, out security))
492 transactionHandler.AddOpenOrder(order, algorithm);
495 Log.
Trace($
"BrokerageSetupHandler.Setup(): Has open order: {order}");
496 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.");
505 private void AddInitializationError(
string message, Exception inner =
null)
507 Errors.Add(
new AlgorithmSetupException(
"During the algorithm initialization, the following exception has occurred: " + message, inner));
516 _factory?.DisposeSafely();
518 if (_dataQueueHandlerBrokerage !=
null)
524 _dataQueueHandlerBrokerage.DisposeSafely();
529 if (dataQueueHandler !=
null)
531 Log.
Trace($
"BrokerageSetupHandler.Setup(): Found data queue handler to dispose: {dataQueueHandler.GetType()}");
532 dataQueueHandler.DisposeSafely();
536 Log.
Trace(
"BrokerageSetupHandler.Setup(): did not find any data queue handler to dispose");
544 var dataQueueHandlerType = Assembly.GetAssembly(typeof(
Brokerage))
547 x.FullName !=
null &&
551 if (dataQueueHandlerType !=
null)
556 if (attribute.Type != factory.GetType())
558 var brokerageFactory = (
BrokerageFactory)Activator.CreateInstance(attribute.Type);
561 foreach (var kvp
in brokerageFactory.BrokerageData)
570 _dataQueueHandlerBrokerage = brokerageFactory.CreateBrokerage(liveJob, algorithm);
573 _dataQueueHandlerBrokerage.
Connect();