public override Dividends GetDividends(Int64Value input) { Assert(Context.CurrentHeight > input.Value, "Cannot query dividends of a future block."); var dividends = State.DonatedDividends[input.Value]; if (dividends != null && dividends.Value.ContainsKey(Context.Variables.NativeSymbol)) { dividends.Value[Context.Variables.NativeSymbol] = dividends.Value[Context.Variables.NativeSymbol].Add(State.MiningReward.Value); } else { dividends = new Dividends { Value = { { Context.Variables.NativeSymbol, State.MiningReward.Value } } }; } return(dividends); }
public async Task <IActionResult> Edit(DateTime id, [Bind("Exe_date,Pay_date,Rec_date,Amount,Dividends_type")] Dividends dividends) { if (id != dividends.Exe_date) { return(NotFound()); } if (ModelState.IsValid) { try { _context.Update(dividends); await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!DividendsExists(dividends.Exe_date)) { return(NotFound()); } else { throw; } } return(RedirectToAction(nameof(Index))); } return(View(dividends)); }
/// <summary> /// Merge two slice with same Time /// </summary> /// <param name="inputSlice">slice instance</param> /// <remarks> Will change the input collection for re-use</remarks> public void MergeSlice(Slice inputSlice) { if (UtcTime != inputSlice.UtcTime) { throw new InvalidOperationException($"Slice with time {UtcTime} can't be merged with given slice with different {inputSlice.UtcTime}"); } _bars = (TradeBars)UpdateCollection(_bars, inputSlice.Bars); _quoteBars = (QuoteBars)UpdateCollection(_quoteBars, inputSlice.QuoteBars); _ticks = (Ticks)UpdateCollection(_ticks, inputSlice.Ticks); _optionChains = (OptionChains)UpdateCollection(_optionChains, inputSlice.OptionChains); _futuresChains = (FuturesChains)UpdateCollection(_futuresChains, inputSlice.FuturesChains); _splits = (Splits)UpdateCollection(_splits, inputSlice.Splits); _dividends = (Dividends)UpdateCollection(_dividends, inputSlice.Dividends); _delistings = (Delistings)UpdateCollection(_delistings, inputSlice.Delistings); _symbolChangedEvents = (SymbolChangedEvents)UpdateCollection(_symbolChangedEvents, inputSlice.SymbolChangedEvents); if (inputSlice._rawDataList.Count != 0) { if (_rawDataList.Count == 0) { _rawDataList = inputSlice._rawDataList; _data = inputSlice._data; } else { // Should keep this._rawDataList last so that selected data points are not overriden // while creating _data inputSlice._rawDataList.AddRange(_rawDataList); _rawDataList = inputSlice._rawDataList; _data = new Lazy <DataDictionary <SymbolData> >(() => CreateDynamicDataDictionary(_rawDataList)); } } }
public IEnumerable <TimeSlice> GetTimeSlices() { var bars = new TradeBars(); var quotes = new QuoteBars(); var ticks = new Ticks(); var options = new OptionChains(); var futures = new FuturesChains(); var splits = new Splits(); var dividends = new Dividends(); var delistings = new Delistings(); var symbolChanges = new SymbolChangedEvents(); var dataFeedPackets = new List <DataFeedPacket>(); var cashUpdateData = new List <UpdateData <Cash> >(); var customData = new List <UpdateData <Security> >(); var changes = SecurityChanges.None; do { var slice = new Slice(default(DateTime), _data, bars, quotes, ticks, options, futures, splits, dividends, delistings, symbolChanges); var timeSlice = new TimeSlice(_frontierUtc, _data.Count, slice, dataFeedPackets, cashUpdateData, securitiesUpdateData, _consolidatorUpdateData, customData, changes); yield return(timeSlice); _frontierUtc += FrontierStepSize; }while (_frontierUtc <= _endTimeUtc); }
/* * New data arrives here. * The "Slice" data represents a slice of time, it has all the data you need for a moment. */ public override void OnData(Slice data) { // slice has lots of useful information TradeBars bars = data.Bars; Splits splits = data.Splits; Dividends dividends = data.Dividends; //Get just this bar. TradeBar bar; if (bars.ContainsKey("SPY")) { bar = bars["SPY"]; } if (!Portfolio.HoldStock) { // place an order, positive is long, negative is short. // Order("SPY", quantity); // or request a fixed fraction of a specific asset. // +1 = 100% long. -2 = short all capital with 2x leverage. SetHoldings("SPY", 1); // debug message to your console. Time is the algorithm time. // send longer messages to a file - these are capped to 10kb Debug("Purchased SPY on " + Time.ToShortDateString()); //Log("This is a longer message send to log."); } }
private void CheckDividendsReceived(Dividends addDividends, int addStuck, int addMoney) { dbConnection.Received().QueryableTransactionRecords.Where(p => p.ProductSeq == addDividends.ProductSeq && p.SalePrice == null && p.TransactionTime <= addDividends.ExRightDate.Date); dbConnection.Received().SaveChanges(); }
/// <summary> /// 新增配股配息紀錄 /// </summary> /// <param name="dividends"></param> /// <returns></returns> public string AddDividends(Dividends dividends) { dividends.CreateTime = DateTime.Now; dbConnection.Modified(dividends, EntityState.Added); dbConnection.SaveChanges(); return("Success"); }
public void OnData(Dividends data) // update this to Dividends dictionary { foreach (var a in algos) { a.Algo.Portfolio.ProcessDividends(data); a.Algo.OnData(data); } }
public override Empty Donate(DonateInput input) { State.TokenContract.TransferFrom.Send(new TransferFromInput { From = Context.Sender, Symbol = input.Symbol, Amount = input.Amount, To = Context.Self }); State.TokenContract.Approve.Send(new ApproveInput { Symbol = input.Symbol, Amount = input.Amount, Spender = State.TokenHolderContract.Value }); State.TokenHolderContract.ContributeProfits.Send(new ContributeProfitsInput { SchemeManager = Context.Self, Symbol = input.Symbol, Amount = input.Amount }); Context.Fire(new DonationReceived { From = Context.Sender, Symbol = input.Symbol, Amount = input.Amount, PoolContract = Context.Self }); var currentReceivedDividends = State.ReceivedDividends[Context.CurrentHeight]; if (currentReceivedDividends != null && currentReceivedDividends.Value.ContainsKey(input.Symbol)) { currentReceivedDividends.Value[input.Symbol] = currentReceivedDividends.Value[input.Symbol].Add(input.Amount); } else { currentReceivedDividends = new Dividends { Value = { { input.Symbol, input.Amount } } }; } State.ReceivedDividends[Context.CurrentHeight] = currentReceivedDividends; Context.LogDebug(() => $"Contributed {input.Amount} {input.Symbol}s to side chain dividends pool."); return(new Empty()); }
/// <summary> /// Raises the data event. /// </summary> /// <param name="data">Data.</param> public void OnData(Dividends data) // update this to Dividends dictionary { var dividend = data["MSFT"]; Debug($"{dividend.Time.ToStringInvariant("o")} >> DIVIDEND >> {dividend.Symbol} - " + $"{dividend.Distribution.ToStringInvariant("C")} - {Portfolio.Cash} - " + $"{Portfolio["MSFT"].Price.ToStringInvariant("C")}" ); }
private void GetStuckDividendsNum(Dividends addDividends, out int addStuck, out int addMoney) { var ownStuckList = FakeTransactionRecord.transactionRecorList.Where(p => p.ProductSeq == addDividends.ProductSeq && p.SalePrice == null && p.TransactionTime.Date <= addDividends.ExRightDate.Date); addMoney = (int)(ownStuckList.Sum(p => p.Num) * addDividends.CashDividends); addStuck = (int)(ownStuckList.Sum(p => p.Num) * addDividends.StockDividend * 0.1); }
public JsonResult AddDividends(Dividends dividends) { var result = "false"; if (ModelState.IsValid) { result = dividendsRepository.AddDividends(dividends); } return(Json(result, JsonRequestBehavior.AllowGet)); }
public async Task <IActionResult> Create([Bind("Exe_date,Pay_date,Rec_date,Amount,Dividends_type")] Dividends dividends) { if (ModelState.IsValid) { _context.Add(dividends); await _context.SaveChangesAsync(); return(RedirectToAction(nameof(Index))); } return(View(dividends)); }
/// <summary> /// Raises the data event. /// </summary> /// <param name="data">Data.</param> public void OnData(Dividends data) { if (data.ContainsKey(_splitAndDividendSymbol)) { var dividend = data[_splitAndDividendSymbol]; if (Time.Date == new DateTime(2010, 06, 15) && (dividend.Price != 0.5m || dividend.ReferencePrice != 88.8m || dividend.Distribution != 0.5m)) { throw new Exception("Did not receive expected dividend values"); } } }
public IEnumerable <(Tax tax, decimal taxValue)> CalcDividendsTaxes() { if (!Dividends.Any()) { return(null); } else { var result = Dividends.Sum(x => x.ConvertedBasis); var taxProfile = ReportOptions.Profile.TaxesProfiles[TaxClassCodes.Dividends]; return(taxProfile.ApplyTaxes(result)); } }
/// <summary> /// Returns the input dividends if non-null, otherwise produces one fom the dynamic data dictionary /// </summary> private Dividends CreateDividendsCollection(Dividends dividends) { if (dividends != null) { return(dividends); } dividends = new Dividends(Time); foreach (var dividend in _data.Value.Values.Select(x => x.GetData()).OfType <Dividend>()) { dividends[dividend.Symbol] = dividend; } return(dividends); }
private Dividends SetAddDividends(double cashDividends, double stockDividend) { var addDividends = new Dividends() { ProductSeq = FakeProduct.StockProduct1.ProductSeq, CashDividends = cashDividends, StockDividend = stockDividend, ExRightDate = DateTime.Now.AddDays(10), DividendDate = DateTime.Now.AddDays(40), CreateTime = DateTime.Now, }; return(addDividends); }
public Slice(DateTime time, IEnumerable <BaseData> data, TradeBars tradeBars, QuoteBars quoteBars, Ticks ticks, OptionChains optionChains, Splits splits, Dividends dividends, Delistings delistings, SymbolChangedEvents symbolChanges, bool?hasData = null) { Time = time; _dataByType = new Dictionary <Type, Lazy <object> >(); _data = new Lazy <DataDictionary <SymbolData> >(() => CreateDynamicDataDictionary(data)); HasData = hasData ?? _data.Value.Count > 0; _ticks = CreateTicksCollection(ticks); _bars = CreateCollection <TradeBars, TradeBar>(tradeBars); _quoteBars = CreateCollection <QuoteBars, QuoteBar>(quoteBars); _optionChains = CreateCollection <OptionChains, OptionChain>(optionChains); _splits = CreateCollection <Splits, Split>(splits); _dividends = CreateCollection <Dividends, Dividend>(dividends); _delistings = CreateCollection <Delistings, Delisting>(delistings); _symbolChangedEvents = CreateCollection <SymbolChangedEvents, SymbolChangedEvent>(symbolChanges); }
/// <summary> /// Initializes a new instance of the <see cref="Slice"/> class /// </summary> /// <param name="time">The timestamp for this slice of data</param> /// <param name="data">The raw data in this slice</param> /// <param name="tradeBars">The trade bars for this slice</param> /// <param name="ticks">This ticks for this slice</param> /// <param name="splits">The splits for this slice</param> /// <param name="dividends">The dividends for this slice</param> /// <param name="delistings">The delistings for this slice</param> public Slice(DateTime time, IEnumerable <BaseData> data, TradeBars tradeBars, Ticks ticks, Splits splits, Dividends dividends, Delistings delistings) { Time = time; _dataByType = new Dictionary <Type, Lazy <object> >(); // market data _data = CreateDynamicDataDictionary(data); _ticks = CreateTicksCollection(ticks); _bars = CreateTradeBarsCollection(tradeBars); // auxiliary data _splits = CreateSplitsCollection(splits); _dividends = CreateDividendsCollection(dividends); _delistings = CreateDelistingsCollection(delistings); }
internal void ProcessDividends(Dividends data) { foreach (var dividend in data) { if (Securities[dividend.Key].DataNormalizationMode == DataNormalizationMode.Raw || Securities[dividend.Key].DataNormalizationMode == DataNormalizationMode.SplitAdjusted || Securities[dividend.Key].DataNormalizationMode == DataNormalizationMode.TotalReturn) { throw new NotImplementedException(); } else { //ignore nothing to do dividends are included in the price } } }
/// <summary> /// Initializes a new instance of the <see cref="Slice"/> class /// </summary> /// <param name="time">The timestamp for this slice of data</param> /// <param name="data">The raw data in this slice</param> /// <param name="tradeBars">The trade bars for this slice</param> /// <param name="ticks">This ticks for this slice</param> /// <param name="splits">The splits for this slice</param> /// <param name="dividends">The dividends for this slice</param> /// <param name="delistings">The delistings for this slice</param> /// <param name="symbolChanges">The symbol changed events for this slice</param> public Slice(DateTime time, IEnumerable <BaseData> data, TradeBars tradeBars, Ticks ticks, Splits splits, Dividends dividends, Delistings delistings, SymbolChangedEvents symbolChanges) { Time = time; _dataByType = new Dictionary <Type, Lazy <object> >(); // market data _data = CreateDynamicDataDictionary(data); _ticks = CreateTicksCollection(ticks); _bars = CreateCollection <TradeBars, TradeBar>(tradeBars); // auxiliary data _splits = CreateCollection <Splits, Split>(splits); _dividends = CreateCollection <Dividends, Dividend>(dividends); _delistings = CreateCollection <Delistings, Delisting>(delistings); _symbolChangedEvents = CreateCollection <SymbolChangedEvents, SymbolChangedEvent>(symbolChanges); }
public void SetDividendsSchedule_OwnStuckIsNull() { var addDividends = new Dividends() { ProductSeq = 99 }; dividendsRepository.SetDividendsSchedule(addDividends); dbConnection.Received().QueryableTransactionRecords.Where(p => p.ProductSeq == addDividends.ProductSeq && p.SalePrice == null && p.TransactionTime <= addDividends.ExRightDate.Date); //確認沒有進入AddTransaction的重新計算資產的 dbConnection.DidNotReceive().Modified(Arg.Is <TransactionRecord>(p => p.ProductSeq == addDividends.ProductSeq), EntityState.Added); dbConnection.DidNotReceive().QueryableAssets.FirstOrDefault(p => p.ProductSeq == addDividends.ProductSeq); dbConnection.DidNotReceive().SaveChanges(); }
/// <summary> /// Initializes a new instance of the <see cref="Slice"/> class /// </summary> /// <param name="time">The timestamp for this slice of data</param> /// <param name="data">The raw data in this slice</param> /// <param name="tradeBars">The trade bars for this slice</param> /// <param name="quoteBars">The quote bars for this slice</param> /// <param name="ticks">This ticks for this slice</param> /// <param name="optionChains">The option chains for this slice</param> /// <param name="futuresChains">The futures chains for this slice</param> /// <param name="splits">The splits for this slice</param> /// <param name="dividends">The dividends for this slice</param> /// <param name="delistings">The delistings for this slice</param> /// <param name="symbolChanges">The symbol changed events for this slice</param> /// <param name="hasData">true if this slice contains data</param> public Slice(DateTime time, IEnumerable <BaseData> data, TradeBars tradeBars, QuoteBars quoteBars, Ticks ticks, OptionChains optionChains, FuturesChains futuresChains, Splits splits, Dividends dividends, Delistings delistings, SymbolChangedEvents symbolChanges, bool?hasData = null) { Time = time; // market data _data = new Lazy <DataDictionary <SymbolData> >(() => CreateDynamicDataDictionary(data)); HasData = hasData ?? _data.Value.Count > 0; _ticks = ticks; _bars = tradeBars; _quoteBars = quoteBars; _optionChains = optionChains; _futuresChains = futuresChains; // auxiliary data _splits = splits; _dividends = dividends; _delistings = delistings; _symbolChangedEvents = symbolChanges; }
/// <summary> /// 配股日到後根據資料表對交易紀錄跟資產做加減 /// </summary> /// <param name="dividends"></param> public void SetDividendsSchedule(Dividends dividends) { if (dividends.ProductSeq == 0) { throw new DataKeyIsNullException(); } //todo 修改配股配息的條件為判斷賣出日 var ownStuckList = dbConnection.QueryableTransactionRecords.Where(p => p.ProductSeq == dividends.ProductSeq && (p.SaleTime == null || p.SaleTime <= dividends.ExRightDate) ).ToList(); if (!ownStuckList.Any()) { return; } var addMoney = (int)(ownStuckList.Sum(p => p.Num) * dividends.CashDividends); var addStuck = (int)(ownStuckList.Sum(p => p.Num) * dividends.StockDividend * 0.1); //新增transaction var transaction = new TransactionViewModel() { SoldStatus = false, ProductSeq = dividends.ProductSeq, Num = addStuck, CashDividends = addMoney, UnitPrice = 0, Fee = 0, isDividends = true, Remark = $"{DateTime.Now.ToString("yyyy")} 股利,配股 {dividends.StockDividend} /配息 {dividends.CashDividends} 。", TransactionTime = DateTime.Now, }; //新增交易紀錄 transactionRepository.AddTransactionLog(transaction); dividends.TransactionRecordSeq = dbConnection.QueryableTransactionRecords.Max(p => p.Seq); dbConnection.SaveChanges(); }
/// <summary> /// Initializes a new instance used by the <see cref="PythonSlice"/> /// </summary> /// <param name="slice">slice object to wrap</param> /// <remarks>This is required so that python slice enumeration works correctly since it relies on the private <see cref="_data"/> collection</remarks> protected Slice(Slice slice) { Time = slice.Time; _dataByType = slice._dataByType; _data = slice._data; HasData = slice.HasData; _ticks = slice._ticks; _bars = slice._bars; _quoteBars = slice._quoteBars; _optionChains = slice._optionChains; _futuresChains = slice._futuresChains; // auxiliary data _splits = slice._splits; _dividends = slice._dividends; _delistings = slice._delistings; _symbolChangedEvents = slice._symbolChangedEvents; }
/// <summary> /// Creates a new <see cref="TimeSlice"/> for the specified time using the specified data /// </summary> /// <param name="utcDateTime">The UTC frontier date time</param> /// <param name="algorithmTimeZone">The algorithm's time zone, required for computing algorithm and slice time</param> /// <param name="cashBook">The algorithm's cash book, required for generating cash update pairs</param> /// <param name="data">The data in this <see cref="TimeSlice"/></param> /// <param name="changes">The new changes that are seen in this time slice as a result of universe selection</param> /// <returns>A new <see cref="TimeSlice"/> containing the specified data</returns> public static TimeSlice Create(DateTime utcDateTime, DateTimeZone algorithmTimeZone, CashBook cashBook, List <DataFeedPacket> data, SecurityChanges changes) { int count = 0; var security = new List <UpdateData <Security> >(); var custom = new List <UpdateData <Security> >(); var consolidator = new List <UpdateData <SubscriptionDataConfig> >(); var allDataForAlgorithm = new List <BaseData>(data.Count); var cash = new List <UpdateData <Cash> >(cashBook.Count); var cashSecurities = new HashSet <Symbol>(); foreach (var cashItem in cashBook.Values) { cashSecurities.Add(cashItem.SecuritySymbol); } Split split; Dividend dividend; Delisting delisting; SymbolChangedEvent symbolChange; // we need to be able to reference the slice being created in order to define the // evaluation of option price models, so we define a 'future' that can be referenced // in the option price model evaluation delegates for each contract Slice slice = null; var sliceFuture = new Lazy <Slice>(() => slice); var algorithmTime = utcDateTime.ConvertFromUtc(algorithmTimeZone); var tradeBars = new TradeBars(algorithmTime); var quoteBars = new QuoteBars(algorithmTime); var ticks = new Ticks(algorithmTime); var splits = new Splits(algorithmTime); var dividends = new Dividends(algorithmTime); var delistings = new Delistings(algorithmTime); var optionChains = new OptionChains(algorithmTime); var futuresChains = new FuturesChains(algorithmTime); var symbolChanges = new SymbolChangedEvents(algorithmTime); foreach (var packet in data) { var list = packet.Data; var symbol = packet.Security.Symbol; if (list.Count == 0) { continue; } // keep count of all data points if (list.Count == 1 && list[0] is BaseDataCollection) { var baseDataCollectionCount = ((BaseDataCollection)list[0]).Data.Count; if (baseDataCollectionCount == 0) { continue; } count += baseDataCollectionCount; } else { count += list.Count; } if (!packet.Configuration.IsInternalFeed && packet.Configuration.IsCustomData) { // This is all the custom data custom.Add(new UpdateData <Security>(packet.Security, packet.Configuration.Type, list)); } var securityUpdate = new List <BaseData>(list.Count); var consolidatorUpdate = new List <BaseData>(list.Count); for (int i = 0; i < list.Count; i++) { var baseData = list[i]; if (!packet.Configuration.IsInternalFeed) { // this is all the data that goes into the algorithm allDataForAlgorithm.Add(baseData); } // don't add internal feed data to ticks/bars objects if (baseData.DataType != MarketDataType.Auxiliary) { if (!packet.Configuration.IsInternalFeed) { PopulateDataDictionaries(baseData, ticks, tradeBars, quoteBars, optionChains, futuresChains); // special handling of options data to build the option chain if (packet.Security.Type == SecurityType.Option) { if (baseData.DataType == MarketDataType.OptionChain) { optionChains[baseData.Symbol] = (OptionChain)baseData; } else if (!HandleOptionData(algorithmTime, baseData, optionChains, packet.Security, sliceFuture)) { continue; } } // special handling of futures data to build the futures chain if (packet.Security.Type == SecurityType.Future) { if (baseData.DataType == MarketDataType.FuturesChain) { futuresChains[baseData.Symbol] = (FuturesChain)baseData; } else if (!HandleFuturesData(algorithmTime, baseData, futuresChains, packet.Security)) { continue; } } // this is data used to update consolidators consolidatorUpdate.Add(baseData); } // this is the data used set market prices // do not add it if it is a Suspicious tick var tick = baseData as Tick; if (tick != null && tick.Suspicious) { continue; } securityUpdate.Add(baseData); } // include checks for various aux types so we don't have to construct the dictionaries in Slice else if ((delisting = baseData as Delisting) != null) { delistings[symbol] = delisting; } else if ((dividend = baseData as Dividend) != null) { dividends[symbol] = dividend; } else if ((split = baseData as Split) != null) { splits[symbol] = split; } else if ((symbolChange = baseData as SymbolChangedEvent) != null) { // symbol changes is keyed by the requested symbol symbolChanges[packet.Configuration.Symbol] = symbolChange; } } if (securityUpdate.Count > 0) { // check for 'cash securities' if we found valid update data for this symbol // and we need this data to update cash conversion rates, long term we should // have Cash hold onto it's security, then he can update himself, or rather, just // patch through calls to conversion rate to compue it on the fly using Security.Price if (cashSecurities.Contains(packet.Security.Symbol)) { foreach (var cashKvp in cashBook) { if (cashKvp.Value.SecuritySymbol == packet.Security.Symbol) { var cashUpdates = new List <BaseData> { securityUpdate[securityUpdate.Count - 1] }; cash.Add(new UpdateData <Cash>(cashKvp.Value, packet.Configuration.Type, cashUpdates)); } } } security.Add(new UpdateData <Security>(packet.Security, packet.Configuration.Type, securityUpdate)); } if (consolidatorUpdate.Count > 0) { consolidator.Add(new UpdateData <SubscriptionDataConfig>(packet.Configuration, packet.Configuration.Type, consolidatorUpdate)); } } slice = new Slice(algorithmTime, allDataForAlgorithm, tradeBars, quoteBars, ticks, optionChains, futuresChains, splits, dividends, delistings, symbolChanges, allDataForAlgorithm.Count > 0); return(new TimeSlice(utcDateTime, count, slice, data, cash, security, consolidator, custom, changes)); }
/// <summary> /// Raises the data event. /// </summary> /// <param name="data">Data.</param> public void OnData(Dividends data) // update this to Dividends dictionary { var dividend = data["MSFT"]; Console.WriteLine("{0} >> DIVIDEND >> {1} - {2} - {3} - {4}", dividend.Time.ToString("o"), dividend.Symbol, dividend.Distribution.ToString("C"), Portfolio.Cash, Portfolio["MSFT"].Price.ToString("C")); }
/// <summary> /// Creates a new <see cref="TimeSlice"/> for the specified time using the specified data /// </summary> /// <param name="utcDateTime">The UTC frontier date time</param> /// <param name="algorithmTimeZone">The algorithm's time zone, required for computing algorithm and slice time</param> /// <param name="cashBook">The algorithm's cash book, required for generating cash update pairs</param> /// <param name="data">The data in this <see cref="TimeSlice"/></param> /// <param name="changes">The new changes that are seen in this time slice as a result of universe selection</param> /// <returns>A new <see cref="TimeSlice"/> containing the specified data</returns> public static TimeSlice Create(DateTime utcDateTime, DateTimeZone algorithmTimeZone, CashBook cashBook, List<KeyValuePair<Security, List<BaseData>>> data, SecurityChanges changes) { int count = 0; var security = new List<KeyValuePair<Security, BaseData>>(); var custom = new List<KeyValuePair<Security, List<BaseData>>>(); var consolidator = new List<KeyValuePair<SubscriptionDataConfig, List<BaseData>>>(); var allDataForAlgorithm = new List<BaseData>(data.Count); var cash = new List<KeyValuePair<Cash, BaseData>>(cashBook.Count); var cashSecurities = new HashSet<Symbol>(); foreach (var cashItem in cashBook.Values) { cashSecurities.Add(cashItem.SecuritySymbol); } Split split; Dividend dividend; Delisting delisting; SymbolChangedEvent symbolChange; var algorithmTime = utcDateTime.ConvertFromUtc(algorithmTimeZone); var tradeBars = new TradeBars(algorithmTime); var ticks = new Ticks(algorithmTime); var splits = new Splits(algorithmTime); var dividends = new Dividends(algorithmTime); var delistings = new Delistings(algorithmTime); var symbolChanges = new SymbolChangedEvents(algorithmTime); foreach (var kvp in data) { var list = kvp.Value; var symbol = kvp.Key.Symbol; // keep count of all data points if (list.Count == 1 && list[0] is BaseDataCollection) { count += ((BaseDataCollection) list[0]).Data.Count; } else { count += list.Count; } BaseData update = null; var consolidatorUpdate = new List<BaseData>(list.Count); for (int i = 0; i < list.Count; i++) { var baseData = list[i]; if (!kvp.Key.SubscriptionDataConfig.IsInternalFeed) { // this is all the data that goes into the algorithm allDataForAlgorithm.Add(baseData); if (kvp.Key.SubscriptionDataConfig.IsCustomData) { // this is all the custom data custom.Add(kvp); } } // don't add internal feed data to ticks/bars objects if (baseData.DataType != MarketDataType.Auxiliary) { if (!kvp.Key.SubscriptionDataConfig.IsInternalFeed) { // populate ticks and tradebars dictionaries with no aux data if (baseData.DataType == MarketDataType.Tick) { List<Tick> ticksList; if (!ticks.TryGetValue(symbol, out ticksList)) { ticksList = new List<Tick> {(Tick) baseData}; ticks[symbol] = ticksList; } ticksList.Add((Tick) baseData); } else if (baseData.DataType == MarketDataType.TradeBar) { tradeBars[symbol] = (TradeBar) baseData; } // this is data used to update consolidators consolidatorUpdate.Add(baseData); } // this is the data used set market prices update = baseData; } // include checks for various aux types so we don't have to construct the dictionaries in Slice else if ((delisting = baseData as Delisting) != null) { delistings[symbol] = delisting; } else if ((dividend = baseData as Dividend) != null) { dividends[symbol] = dividend; } else if ((split = baseData as Split) != null) { splits[symbol] = split; } else if ((symbolChange = baseData as SymbolChangedEvent) != null) { // symbol changes is keyed by the requested symbol symbolChanges[kvp.Key.SubscriptionDataConfig.Symbol] = symbolChange; } } // check for 'cash securities' if we found valid update data for this symbol // and we need this data to update cash conversion rates, long term we should // have Cash hold onto it's security, then he can update himself, or rather, just // patch through calls to conversion rate to compue it on the fly using Security.Price if (update != null && cashSecurities.Contains(kvp.Key.Symbol)) { foreach (var cashKvp in cashBook) { if (cashKvp.Value.SecuritySymbol == kvp.Key.Symbol) { cash.Add(new KeyValuePair<Cash, BaseData>(cashKvp.Value, update)); } } } security.Add(new KeyValuePair<Security, BaseData>(kvp.Key, update)); consolidator.Add(new KeyValuePair<SubscriptionDataConfig, List<BaseData>>(kvp.Key.SubscriptionDataConfig, consolidatorUpdate)); } var slice = new Slice(utcDateTime.ConvertFromUtc(algorithmTimeZone), allDataForAlgorithm, tradeBars, ticks, splits, dividends, delistings, symbolChanges, allDataForAlgorithm.Count > 0); return new TimeSlice(utcDateTime, count, slice, data, cash, security, consolidator, custom, changes); }
/// <summary> /// Creates a new <see cref="TimeSlice"/> for the specified time using the specified data /// </summary> /// <param name="utcDateTime">The UTC frontier date time</param> /// <param name="data">The data in this <see cref="TimeSlice"/></param> /// <param name="changes">The new changes that are seen in this time slice as a result of universe selection</param> /// <param name="universeData"></param> /// <returns>A new <see cref="TimeSlice"/> containing the specified data</returns> public TimeSlice Create(DateTime utcDateTime, List <DataFeedPacket> data, SecurityChanges changes, Dictionary <Universe, BaseDataCollection> universeData) { int count = 0; var security = new List <UpdateData <ISecurityPrice> >(data.Count); List <UpdateData <ISecurityPrice> > custom = null; var consolidator = new List <UpdateData <SubscriptionDataConfig> >(data.Count); var allDataForAlgorithm = new List <BaseData>(data.Count); var optionUnderlyingUpdates = new Dictionary <Symbol, BaseData>(); Split split; Dividend dividend; Delisting delisting; SymbolChangedEvent symbolChange; // we need to be able to reference the slice being created in order to define the // evaluation of option price models, so we define a 'future' that can be referenced // in the option price model evaluation delegates for each contract Slice slice = null; var sliceFuture = new Lazy <Slice>(() => slice); var algorithmTime = utcDateTime.ConvertFromUtc(_timeZone); TradeBars tradeBars = null; QuoteBars quoteBars = null; Ticks ticks = null; Splits splits = null; Dividends dividends = null; Delistings delistings = null; OptionChains optionChains = null; FuturesChains futuresChains = null; SymbolChangedEvents symbolChanges = null; UpdateEmptyCollections(algorithmTime); if (universeData.Count > 0) { // count universe data foreach (var kvp in universeData) { count += kvp.Value.Data.Count; } } // ensure we read equity data before option data, so we can set the current underlying price foreach (var packet in data) { // filter out packets for removed subscriptions if (packet.IsSubscriptionRemoved) { continue; } var list = packet.Data; var symbol = packet.Configuration.Symbol; if (list.Count == 0) { continue; } // keep count of all data points if (list.Count == 1 && list[0] is BaseDataCollection) { var baseDataCollectionCount = ((BaseDataCollection)list[0]).Data.Count; if (baseDataCollectionCount == 0) { continue; } count += baseDataCollectionCount; } else { count += list.Count; } if (!packet.Configuration.IsInternalFeed && packet.Configuration.IsCustomData) { if (custom == null) { custom = new List <UpdateData <ISecurityPrice> >(1); } // This is all the custom data custom.Add(new UpdateData <ISecurityPrice>(packet.Security, packet.Configuration.Type, list, packet.Configuration.IsInternalFeed)); } var securityUpdate = new List <BaseData>(list.Count); var consolidatorUpdate = new List <BaseData>(list.Count); var containsFillForwardData = false; for (var i = 0; i < list.Count; i++) { var baseData = list[i]; if (!packet.Configuration.IsInternalFeed) { // this is all the data that goes into the algorithm allDataForAlgorithm.Add(baseData); } containsFillForwardData |= baseData.IsFillForward; // don't add internal feed data to ticks/bars objects if (baseData.DataType != MarketDataType.Auxiliary) { var tick = baseData as Tick; if (!packet.Configuration.IsInternalFeed) { // populate data dictionaries switch (baseData.DataType) { case MarketDataType.Tick: if (ticks == null) { ticks = new Ticks(algorithmTime); } ticks.Add(baseData.Symbol, (Tick)baseData); break; case MarketDataType.TradeBar: if (tradeBars == null) { tradeBars = new TradeBars(algorithmTime); } var newTradeBar = (TradeBar)baseData; TradeBar existingTradeBar; // if we have an existing bar keep the highest resolution one // e.g Hour and Minute resolution subscriptions for the same symbol // see CustomUniverseWithBenchmarkRegressionAlgorithm if (!tradeBars.TryGetValue(baseData.Symbol, out existingTradeBar) || existingTradeBar.Period > newTradeBar.Period) { tradeBars[baseData.Symbol] = newTradeBar; } break; case MarketDataType.QuoteBar: if (quoteBars == null) { quoteBars = new QuoteBars(algorithmTime); } var newQuoteBar = (QuoteBar)baseData; QuoteBar existingQuoteBar; // if we have an existing bar keep the highest resolution one // e.g Hour and Minute resolution subscriptions for the same symbol // see CustomUniverseWithBenchmarkRegressionAlgorithm if (!quoteBars.TryGetValue(baseData.Symbol, out existingQuoteBar) || existingQuoteBar.Period > newQuoteBar.Period) { quoteBars[baseData.Symbol] = newQuoteBar; } break; case MarketDataType.OptionChain: if (optionChains == null) { optionChains = new OptionChains(algorithmTime); } optionChains[baseData.Symbol] = (OptionChain)baseData; break; case MarketDataType.FuturesChain: if (futuresChains == null) { futuresChains = new FuturesChains(algorithmTime); } futuresChains[baseData.Symbol] = (FuturesChain)baseData; break; } // this is data used to update consolidators // do not add it if it is a Suspicious tick if (tick == null || !tick.Suspicious) { consolidatorUpdate.Add(baseData); } } // special handling of options data to build the option chain if (symbol.SecurityType.IsOption()) { // internal feeds, like open interest, will not create the chain but will update it if it exists // this is because the open interest could arrive at some closed market hours in which there is no other data and we don't // want to generate a chain object in this case if (optionChains == null && !packet.Configuration.IsInternalFeed) { optionChains = new OptionChains(algorithmTime); } if (baseData.DataType == MarketDataType.OptionChain) { optionChains[baseData.Symbol] = (OptionChain)baseData; } else if (optionChains != null && !HandleOptionData(algorithmTime, baseData, optionChains, packet.Security, sliceFuture, optionUnderlyingUpdates)) { continue; } } // special handling of futures data to build the futures chain if (symbol.SecurityType == SecurityType.Future) { // internal feeds, like open interest, will not create the chain but will update it if it exists // this is because the open interest could arrive at some closed market hours in which there is no other data and we don't // want to generate a chain object in this case if (futuresChains == null && !packet.Configuration.IsInternalFeed) { futuresChains = new FuturesChains(algorithmTime); } if (baseData.DataType == MarketDataType.FuturesChain) { futuresChains[baseData.Symbol] = (FuturesChain)baseData; } else if (futuresChains != null && !HandleFuturesData(algorithmTime, baseData, futuresChains, packet.Security)) { continue; } } // this is the data used set market prices // do not add it if it is a Suspicious tick if (tick != null && tick.Suspicious) { continue; } securityUpdate.Add(baseData); // option underlying security update if (!packet.Configuration.IsInternalFeed) { optionUnderlyingUpdates[symbol] = baseData; } } else if (!packet.Configuration.IsInternalFeed) { // include checks for various aux types so we don't have to construct the dictionaries in Slice if ((delisting = baseData as Delisting) != null) { if (delistings == null) { delistings = new Delistings(algorithmTime); } delistings[symbol] = delisting; } else if ((dividend = baseData as Dividend) != null) { if (dividends == null) { dividends = new Dividends(algorithmTime); } dividends[symbol] = dividend; } else if ((split = baseData as Split) != null) { if (splits == null) { splits = new Splits(algorithmTime); } splits[symbol] = split; } else if ((symbolChange = baseData as SymbolChangedEvent) != null) { if (symbolChanges == null) { symbolChanges = new SymbolChangedEvents(algorithmTime); } // symbol changes is keyed by the requested symbol symbolChanges[packet.Configuration.Symbol] = symbolChange; } } } if (securityUpdate.Count > 0) { security.Add(new UpdateData <ISecurityPrice>(packet.Security, packet.Configuration.Type, securityUpdate, packet.Configuration.IsInternalFeed, containsFillForwardData)); } if (consolidatorUpdate.Count > 0) { consolidator.Add(new UpdateData <SubscriptionDataConfig>(packet.Configuration, packet.Configuration.Type, consolidatorUpdate, packet.Configuration.IsInternalFeed, containsFillForwardData)); } } slice = new Slice(algorithmTime, allDataForAlgorithm, tradeBars ?? _emptyTradeBars, quoteBars ?? _emptyQuoteBars, ticks ?? _emptyTicks, optionChains ?? _emptyOptionChains, futuresChains ?? _emptyFuturesChains, splits ?? _emptySplits, dividends ?? _emptyDividends, delistings ?? _emptyDelistings, symbolChanges ?? _emptySymbolChangedEvents, allDataForAlgorithm.Count > 0); return(new TimeSlice(utcDateTime, count, slice, data, security, consolidator, custom ?? _emptyCustom, changes, universeData)); }
/// <summary> /// Launch the algorithm manager to run this strategy /// </summary> /// <param name="job">Algorithm job</param> /// <param name="algorithm">Algorithm instance</param> /// <param name="feed">Datafeed object</param> /// <param name="transactions">Transaction manager object</param> /// <param name="results">Result handler object</param> /// <param name="realtime">Realtime processing object</param> /// <param name="token">Cancellation token</param> /// <remarks>Modify with caution</remarks> public void Run(AlgorithmNodePacket job, IAlgorithm algorithm, IDataFeed feed, ITransactionHandler transactions, IResultHandler results, IRealTimeHandler realtime, CancellationToken token) { //Initialize: _dataPointCount = 0; var startingPortfolioValue = algorithm.Portfolio.TotalPortfolioValue; var backtestMode = (job.Type == PacketType.BacktestNode); var methodInvokers = new Dictionary <Type, MethodInvoker>(); var marginCallFrequency = TimeSpan.FromMinutes(5); var nextMarginCallTime = DateTime.MinValue; var delistingTickets = new List <OrderTicket>(); //Initialize Properties: _algorithmId = job.AlgorithmId; _algorithmState = AlgorithmStatus.Running; _previousTime = algorithm.StartDate.Date; //Create the method accessors to push generic types into algorithm: Find all OnData events: // Algorithm 2.0 data accessors var hasOnDataTradeBars = AddMethodInvoker <TradeBars>(algorithm, methodInvokers); var hasOnDataTicks = AddMethodInvoker <Ticks>(algorithm, methodInvokers); // dividend and split events var hasOnDataDividends = AddMethodInvoker <Dividends>(algorithm, methodInvokers); var hasOnDataSplits = AddMethodInvoker <Splits>(algorithm, methodInvokers); var hasOnDataDelistings = AddMethodInvoker <Delistings>(algorithm, methodInvokers); // Algorithm 3.0 data accessors var hasOnDataSlice = algorithm.GetType().GetMethods() .Where(x => x.Name == "OnData" && x.GetParameters().Length == 1 && x.GetParameters()[0].ParameterType == typeof(Slice)) .FirstOrDefault(x => x.DeclaringType == algorithm.GetType()) != null; //Go through the subscription types and create invokers to trigger the event handlers for each custom type: foreach (var config in feed.Subscriptions) { //If type is a tradebar, combine tradebars and ticks into unified array: if (config.Type.Name != "TradeBar" && config.Type.Name != "Tick") { //Get the matching method for this event handler - e.g. public void OnData(Quandl data) { .. } var genericMethod = (algorithm.GetType()).GetMethod("OnData", new[] { config.Type }); //If we already have this Type-handler then don't add it to invokers again. if (methodInvokers.ContainsKey(config.Type)) { continue; } //If we couldnt find the event handler, let the user know we can't fire that event. if (genericMethod == null && !hasOnDataSlice) { algorithm.RunTimeError = new Exception("Data event handler not found, please create a function matching this template: public void OnData(" + config.Type.Name + " data) { }"); _algorithmState = AlgorithmStatus.RuntimeError; return; } if (genericMethod != null) { methodInvokers.Add(config.Type, genericMethod.DelegateForCallMethod()); } } } //Loop over the queues: get a data collection, then pass them all into relevent methods in the algorithm. Log.Trace("AlgorithmManager.Run(): Begin DataStream - Start: " + algorithm.StartDate + " Stop: " + algorithm.EndDate); foreach (var timeSlice in feed.Bridge.GetConsumingEnumerable(token)) { // reset our timer on each loop _currentTimeStepTime = DateTime.UtcNow; //Check this backtest is still running: if (_algorithmState != AlgorithmStatus.Running) { Log.Error(string.Format("AlgorithmManager.Run(): Algorthm state changed to {0} at {1}", _algorithmState, timeSlice.Time)); break; } //Execute with TimeLimit Monitor: if (token.IsCancellationRequested) { Log.Error("AlgorithmManager.Run(): CancellationRequestion at " + timeSlice.Time); return; } var time = timeSlice.Time; var newData = timeSlice.Data; //If we're in backtest mode we need to capture the daily performance. We do this here directly //before updating the algorithm state with the new data from this time step, otherwise we'll //produce incorrect samples (they'll take into account this time step's new price values) if (backtestMode) { //On day-change sample equity and daily performance for statistics calculations if (_previousTime.Date != time.Date) { //Sample the portfolio value over time for chart. results.SampleEquity(_previousTime, Math.Round(algorithm.Portfolio.TotalPortfolioValue, 4)); //Check for divide by zero if (startingPortfolioValue == 0m) { results.SamplePerformance(_previousTime.Date, 0); } else { results.SamplePerformance(_previousTime.Date, Math.Round((algorithm.Portfolio.TotalPortfolioValue - startingPortfolioValue) * 100 / startingPortfolioValue, 10)); } startingPortfolioValue = algorithm.Portfolio.TotalPortfolioValue; } } //Update algorithm state after capturing performance from previous day //Set the algorithm and real time handler's time algorithm.SetDateTime(time); realtime.SetTime(algorithm.Time); //On each time step push the real time prices to the cashbook so we can have updated conversion rates algorithm.Portfolio.CashBook.Update(newData); //Update the securities properties: first before calling user code to avoid issues with data algorithm.Securities.Update(time, newData); // process fill models on the updated data before entering algorithm, applies to all non-market orders transactions.ProcessSynchronousEvents(); if (delistingTickets.Count != 0) { for (int i = 0; i < delistingTickets.Count; i++) { var ticket = delistingTickets[i]; if (ticket.Status == OrderStatus.Filled) { algorithm.Securities.Remove(ticket.Symbol); delistingTickets.RemoveAt(i--); Log.Trace("AlgorithmManager.Run(): Security removed: " + ticket.Symbol); } } } //Check if the user's signalled Quit: loop over data until day changes. if (algorithm.GetQuit()) { _algorithmState = AlgorithmStatus.Quit; Log.Trace("AlgorithmManager.Run(): Algorithm quit requested."); break; } if (algorithm.RunTimeError != null) { _algorithmState = AlgorithmStatus.RuntimeError; Log.Trace(string.Format("AlgorithmManager.Run(): Algorithm encountered a runtime error at {0}. Error: {1}", timeSlice.Time, algorithm.RunTimeError)); break; } // perform margin calls, in live mode we can also use realtime to emit these if (time >= nextMarginCallTime || (_liveMode && nextMarginCallTime > DateTime.Now)) { // determine if there are possible margin call orders to be executed bool issueMarginCallWarning; var marginCallOrders = algorithm.Portfolio.ScanForMarginCall(out issueMarginCallWarning); if (marginCallOrders.Count != 0) { try { // tell the algorithm we're about to issue the margin call algorithm.OnMarginCall(marginCallOrders); } catch (Exception err) { algorithm.RunTimeError = err; _algorithmState = AlgorithmStatus.RuntimeError; Log.Error("AlgorithmManager.Run(): RuntimeError: OnMarginCall: " + err.Message + " STACK >>> " + err.StackTrace); return; } // execute the margin call orders var executedTickets = algorithm.Portfolio.MarginCallModel.ExecuteMarginCall(marginCallOrders); foreach (var ticket in executedTickets) { algorithm.Error(string.Format("{0} - Executed MarginCallOrder: {1} - Quantity: {2} @ {3}", algorithm.Time, ticket.Symbol, ticket.Quantity, ticket.OrderEvents.Last().FillPrice)); } } // we didn't perform a margin call, but got the warning flag back, so issue the warning to the algorithm else if (issueMarginCallWarning) { try { algorithm.OnMarginCallWarning(); } catch (Exception err) { algorithm.RunTimeError = err; _algorithmState = AlgorithmStatus.RuntimeError; Log.Error("AlgorithmManager.Run(): RuntimeError: OnMarginCallWarning: " + err.Message + " STACK >>> " + err.StackTrace); } } nextMarginCallTime = time + marginCallFrequency; } //Trigger the data events: Invoke the types we have data for: var newBars = new TradeBars(algorithm.Time); var newTicks = new Ticks(algorithm.Time); var newDividends = new Dividends(algorithm.Time); var newSplits = new Splits(algorithm.Time); var newDelistings = new Delistings(algorithm.Time); //Invoke all non-tradebars, non-ticks methods and build up the TradeBars and Ticks dictionaries // --> i == Subscription Configuration Index, so we don't need to compare types. foreach (var i in newData.Keys) { //Data point and config of this point: var dataPoints = newData[i]; var config = feed.Subscriptions[i]; //Keep track of how many data points we've processed _dataPointCount += dataPoints.Count; //We don't want to pump data that we added just for currency conversions if (config.IsInternalFeed) { continue; } //Create TradeBars Unified Data --> OR --> invoke generic data event. One loop. // Aggregate Dividends and Splits -- invoke portfolio application methods foreach (var dataPoint in dataPoints) { var dividend = dataPoint as Dividend; if (dividend != null) { Log.Trace("AlgorithmManager.Run(): Applying Dividend for " + dividend.Symbol); // if this is a dividend apply to portfolio algorithm.Portfolio.ApplyDividend(dividend); if (hasOnDataDividends) { // and add to our data dictionary to pump into OnData(Dividends data) newDividends.Add(dividend); } continue; } var split = dataPoint as Split; if (split != null) { Log.Trace("AlgorithmManager.Run(): Applying Split for " + split.Symbol); // if this is a split apply to portfolio algorithm.Portfolio.ApplySplit(split); if (hasOnDataSplits) { // and add to our data dictionary to pump into OnData(Splits data) newSplits.Add(split); } continue; } var delisting = dataPoint as Delisting; if (delisting != null) { if (hasOnDataDelistings) { // add to out data dictonary to pump into OnData(Delistings data) newDelistings.Add(delisting); } } //Update registered consolidators for this symbol index try { for (var j = 0; j < config.Consolidators.Count; j++) { config.Consolidators[j].Update(dataPoint); } } catch (Exception err) { algorithm.RunTimeError = err; _algorithmState = AlgorithmStatus.RuntimeError; Log.Error("AlgorithmManager.Run(): RuntimeError: Consolidators update: " + err.Message); return; } // TRADEBAR -- add to our dictionary if (dataPoint.DataType == MarketDataType.TradeBar) { var bar = dataPoint as TradeBar; if (bar != null) { newBars[bar.Symbol] = bar; continue; } } // TICK -- add to our dictionary if (dataPoint.DataType == MarketDataType.Tick) { var tick = dataPoint as Tick; if (tick != null) { List <Tick> ticks; if (!newTicks.TryGetValue(tick.Symbol, out ticks)) { ticks = new List <Tick>(3); newTicks.Add(tick.Symbol, ticks); } ticks.Add(tick); continue; } } // if it was nothing else then it must be custom data // CUSTOM DATA -- invoke on data method //Send data into the generic algorithm event handlers try { MethodInvoker methodInvoker; if (methodInvokers.TryGetValue(config.Type, out methodInvoker)) { methodInvoker(algorithm, dataPoint); } } catch (Exception err) { algorithm.RunTimeError = err; _algorithmState = AlgorithmStatus.RuntimeError; Log.Error("AlgorithmManager.Run(): RuntimeError: Custom Data: " + err.Message + " STACK >>> " + err.StackTrace); return; } } } try { // fire off the dividend and split events before pricing events if (hasOnDataDividends && newDividends.Count != 0) { methodInvokers[typeof(Dividends)](algorithm, newDividends); } if (hasOnDataSplits && newSplits.Count != 0) { methodInvokers[typeof(Splits)](algorithm, newSplits); } if (hasOnDataDelistings && newDelistings.Count != 0) { methodInvokers[typeof(Delistings)](algorithm, newDelistings); } } catch (Exception err) { algorithm.RunTimeError = err; _algorithmState = AlgorithmStatus.RuntimeError; Log.Error("AlgorithmManager.Run(): RuntimeError: Dividends/Splits/Delistings: " + err.Message + " STACK >>> " + err.StackTrace); return; } // run the delisting logic after firing delisting events HandleDelistedSymbols(algorithm, newDelistings, delistingTickets); //After we've fired all other events in this second, fire the pricing events: try { if (hasOnDataTradeBars && newBars.Count > 0) { methodInvokers[typeof(TradeBars)](algorithm, newBars); } if (hasOnDataTicks && newTicks.Count > 0) { methodInvokers[typeof(Ticks)](algorithm, newTicks); } } catch (Exception err) { algorithm.RunTimeError = err; _algorithmState = AlgorithmStatus.RuntimeError; Log.Error("AlgorithmManager.Run(): RuntimeError: New Style Mode: " + err.Message + " STACK >>> " + err.StackTrace); return; } // EVENT HANDLER v3.0 -- all data in a single event var slice = new Slice(algorithm.Time, newData.Values.SelectMany(x => x), newBars.Count == 0 ? null : newBars, newTicks.Count == 0 ? null : newTicks, newSplits.Count == 0 ? null : newSplits, newDividends.Count == 0 ? null : newDividends, newDelistings.Count == 0 ? null : newDelistings ); try { algorithm.OnData(slice); } catch (Exception err) { algorithm.RunTimeError = err; _algorithmState = AlgorithmStatus.RuntimeError; Log.Error("AlgorithmManager.Run(): RuntimeError: Slice: " + err.Message + " STACK >>> " + err.StackTrace); return; } //If its the historical/paper trading models, wait until market orders have been "filled" // Manually trigger the event handler to prevent thread switch. transactions.ProcessSynchronousEvents(); //Save the previous time for the sample calculations _previousTime = time; // Process any required events of the results handler such as sampling assets, equity, or stock prices. results.ProcessSynchronousEvents(); } // End of ForEach feed.Bridge.GetConsumingEnumerable // stop timing the loops _currentTimeStepTime = DateTime.MinValue; //Stream over:: Send the final packet and fire final events: Log.Trace("AlgorithmManager.Run(): Firing On End Of Algorithm..."); try { algorithm.OnEndOfAlgorithm(); } catch (Exception err) { _algorithmState = AlgorithmStatus.RuntimeError; algorithm.RunTimeError = new Exception("Error running OnEndOfAlgorithm(): " + err.Message, err.InnerException); Log.Error("AlgorithmManager.OnEndOfAlgorithm(): " + err.Message + " STACK >>> " + err.StackTrace); return; } // Process any required events of the results handler such as sampling assets, equity, or stock prices. results.ProcessSynchronousEvents(forceProcess: true); //Liquidate Holdings for Calculations: if (_algorithmState == AlgorithmStatus.Liquidated && _liveMode) { Log.Trace("AlgorithmManager.Run(): Liquidating algorithm holdings..."); algorithm.Liquidate(); results.LogMessage("Algorithm Liquidated"); results.SendStatusUpdate(job.AlgorithmId, AlgorithmStatus.Liquidated); } //Manually stopped the algorithm if (_algorithmState == AlgorithmStatus.Stopped) { Log.Trace("AlgorithmManager.Run(): Stopping algorithm..."); results.LogMessage("Algorithm Stopped"); results.SendStatusUpdate(job.AlgorithmId, AlgorithmStatus.Stopped); } //Backtest deleted. if (_algorithmState == AlgorithmStatus.Deleted) { Log.Trace("AlgorithmManager.Run(): Deleting algorithm..."); results.DebugMessage("Algorithm Id:(" + job.AlgorithmId + ") Deleted by request."); results.SendStatusUpdate(job.AlgorithmId, AlgorithmStatus.Deleted); } //Algorithm finished, send regardless of commands: results.SendStatusUpdate(job.AlgorithmId, AlgorithmStatus.Completed); //Take final samples: results.SampleRange(algorithm.GetChartUpdates()); results.SampleEquity(_previousTime, Math.Round(algorithm.Portfolio.TotalPortfolioValue, 4)); results.SamplePerformance(_previousTime, Math.Round((algorithm.Portfolio.TotalPortfolioValue - startingPortfolioValue) * 100 / startingPortfolioValue, 10)); } // End of Run();
/// <summary> /// Creates a new <see cref="TimeSlice"/> for the specified time using the specified data /// </summary> /// <param name="utcDateTime">The UTC frontier date time</param> /// <param name="algorithmTimeZone">The algorithm's time zone, required for computing algorithm and slice time</param> /// <param name="cashBook">The algorithm's cash book, required for generating cash update pairs</param> /// <param name="data">The data in this <see cref="TimeSlice"/></param> /// <param name="changes">The new changes that are seen in this time slice as a result of universe selection</param> /// <returns>A new <see cref="TimeSlice"/> containing the specified data</returns> public static TimeSlice Create(DateTime utcDateTime, DateTimeZone algorithmTimeZone, CashBook cashBook, List <DataFeedPacket> data, SecurityChanges changes) { int count = 0; var security = new List <KeyValuePair <Security, BaseData> >(); var custom = new List <KeyValuePair <Security, IEnumerable <BaseData> > >(); var consolidator = new List <KeyValuePair <SubscriptionDataConfig, List <BaseData> > >(); var allDataForAlgorithm = new List <BaseData>(data.Count); var cash = new List <KeyValuePair <Cash, BaseData> >(cashBook.Count); var cashSecurities = new HashSet <Symbol>(); foreach (var cashItem in cashBook.Values) { cashSecurities.Add(cashItem.SecuritySymbol); } Split split; Dividend dividend; Delisting delisting; SymbolChangedEvent symbolChange; var algorithmTime = utcDateTime.ConvertFromUtc(algorithmTimeZone); var tradeBars = new TradeBars(algorithmTime); var ticks = new Ticks(algorithmTime); var splits = new Splits(algorithmTime); var dividends = new Dividends(algorithmTime); var delistings = new Delistings(algorithmTime); var symbolChanges = new SymbolChangedEvents(algorithmTime); foreach (var packet in data) { var list = packet.Data; var symbol = packet.Security.Symbol; // keep count of all data points if (list.Count == 1 && list[0] is BaseDataCollection) { count += ((BaseDataCollection)list[0]).Data.Count; } else { count += list.Count; } BaseData update = null; var consolidatorUpdate = new List <BaseData>(list.Count); for (int i = 0; i < list.Count; i++) { var baseData = list[i]; if (!packet.Security.SubscriptionDataConfig.IsInternalFeed) { // this is all the data that goes into the algorithm allDataForAlgorithm.Add(baseData); if (packet.Security.SubscriptionDataConfig.IsCustomData) { // this is all the custom data custom.Add(new KeyValuePair <Security, IEnumerable <BaseData> >(packet.Security, list)); } } // don't add internal feed data to ticks/bars objects if (baseData.DataType != MarketDataType.Auxiliary) { if (!packet.Security.SubscriptionDataConfig.IsInternalFeed) { // populate ticks and tradebars dictionaries with no aux data switch (baseData.DataType) { case MarketDataType.Tick: List <Tick> ticksList; if (!ticks.TryGetValue(symbol, out ticksList)) { ticksList = new List <Tick> { (Tick)baseData }; ticks[symbol] = ticksList; } ticksList.Add((Tick)baseData); break; case MarketDataType.TradeBar: tradeBars[symbol] = (TradeBar)baseData; break; } // this is data used to update consolidators consolidatorUpdate.Add(baseData); } // this is the data used set market prices update = baseData; } // include checks for various aux types so we don't have to construct the dictionaries in Slice else if ((delisting = baseData as Delisting) != null) { delistings[symbol] = delisting; } else if ((dividend = baseData as Dividend) != null) { dividends[symbol] = dividend; } else if ((split = baseData as Split) != null) { splits[symbol] = split; } else if ((symbolChange = baseData as SymbolChangedEvent) != null) { // symbol changes is keyed by the requested symbol symbolChanges[packet.Security.SubscriptionDataConfig.Symbol] = symbolChange; } } // check for 'cash securities' if we found valid update data for this symbol // and we need this data to update cash conversion rates, long term we should // have Cash hold onto it's security, then he can update himself, or rather, just // patch through calls to conversion rate to compue it on the fly using Security.Price if (update != null && cashSecurities.Contains(packet.Security.Symbol)) { foreach (var cashKvp in cashBook) { if (cashKvp.Value.SecuritySymbol == packet.Security.Symbol) { cash.Add(new KeyValuePair <Cash, BaseData>(cashKvp.Value, update)); } } } security.Add(new KeyValuePair <Security, BaseData>(packet.Security, update)); consolidator.Add(new KeyValuePair <SubscriptionDataConfig, List <BaseData> >(packet.Security.SubscriptionDataConfig, consolidatorUpdate)); } var slice = new Slice(algorithmTime, allDataForAlgorithm, tradeBars, ticks, splits, dividends, delistings, symbolChanges, allDataForAlgorithm.Count > 0); return(new TimeSlice(utcDateTime, count, slice, data, cash, security, consolidator, custom, changes)); }
private DataUpdates(DateTime occuredutc, DataPoint[] dataPoints, Delistings delistings, Dividends dividends, Earnings earnings, Financials financials, KeyStats keystats, QuoteBars quotebars, Splits splits, TradeBars tradebars, TradingStatusUpdates tradingStatusUpdates, Ticks ticks) { //TODO: for cloning this object (so it becomes immutable) throw new NotImplementedException(); }
/// <summary> /// Creates a new <see cref="TimeSlice"/> for the specified time using the specified data /// </summary> /// <param name="utcDateTime">The UTC frontier date time</param> /// <param name="algorithmTimeZone">The algorithm's time zone, required for computing algorithm and slice time</param> /// <param name="cashBook">The algorithm's cash book, required for generating cash update pairs</param> /// <param name="data">The data in this <see cref="TimeSlice"/></param> /// <param name="changes">The new changes that are seen in this time slice as a result of universe selection</param> /// <returns>A new <see cref="TimeSlice"/> containing the specified data</returns> public static TimeSlice Create(DateTime utcDateTime, DateTimeZone algorithmTimeZone, CashBook cashBook, List<DataFeedPacket> data, SecurityChanges changes) { int count = 0; var security = new List<UpdateData<Security>>(); var custom = new List<UpdateData<Security>>(); var consolidator = new List<UpdateData<SubscriptionDataConfig>>(); var allDataForAlgorithm = new List<BaseData>(data.Count); var cash = new List<UpdateData<Cash>>(cashBook.Count); var cashSecurities = new HashSet<Symbol>(); foreach (var cashItem in cashBook.Values) { cashSecurities.Add(cashItem.SecuritySymbol); } Split split; Dividend dividend; Delisting delisting; SymbolChangedEvent symbolChange; // we need to be able to reference the slice being created in order to define the // evaluation of option price models, so we define a 'future' that can be referenced // in the option price model evaluation delegates for each contract Slice slice = null; var sliceFuture = new Lazy<Slice>(() => slice); var algorithmTime = utcDateTime.ConvertFromUtc(algorithmTimeZone); var tradeBars = new TradeBars(algorithmTime); var quoteBars = new QuoteBars(algorithmTime); var ticks = new Ticks(algorithmTime); var splits = new Splits(algorithmTime); var dividends = new Dividends(algorithmTime); var delistings = new Delistings(algorithmTime); var optionChains = new OptionChains(algorithmTime); var symbolChanges = new SymbolChangedEvents(algorithmTime); foreach (var packet in data) { var list = packet.Data; var symbol = packet.Security.Symbol; if (list.Count == 0) continue; // keep count of all data points if (list.Count == 1 && list[0] is BaseDataCollection) { var baseDataCollectionCount = ((BaseDataCollection)list[0]).Data.Count; if (baseDataCollectionCount == 0) { continue; } count += baseDataCollectionCount; } else { count += list.Count; } if (!packet.Configuration.IsInternalFeed && packet.Configuration.IsCustomData) { // This is all the custom data custom.Add(new UpdateData<Security>(packet.Security, packet.Configuration.Type, list)); } var securityUpdate = new List<BaseData>(list.Count); var consolidatorUpdate = new List<BaseData>(list.Count); for (int i = 0; i < list.Count; i++) { var baseData = list[i]; if (!packet.Configuration.IsInternalFeed) { // this is all the data that goes into the algorithm allDataForAlgorithm.Add(baseData); } // don't add internal feed data to ticks/bars objects if (baseData.DataType != MarketDataType.Auxiliary) { if (!packet.Configuration.IsInternalFeed) { PopulateDataDictionaries(baseData, ticks, tradeBars, quoteBars, optionChains); // special handling of options data to build the option chain if (packet.Security.Type == SecurityType.Option) { if (baseData.DataType == MarketDataType.OptionChain) { optionChains[baseData.Symbol] = (OptionChain) baseData; } else if (!HandleOptionData(algorithmTime, baseData, optionChains, packet.Security, sliceFuture)) { continue; } } // this is data used to update consolidators consolidatorUpdate.Add(baseData); } // this is the data used set market prices securityUpdate.Add(baseData); } // include checks for various aux types so we don't have to construct the dictionaries in Slice else if ((delisting = baseData as Delisting) != null) { delistings[symbol] = delisting; } else if ((dividend = baseData as Dividend) != null) { dividends[symbol] = dividend; } else if ((split = baseData as Split) != null) { splits[symbol] = split; } else if ((symbolChange = baseData as SymbolChangedEvent) != null) { // symbol changes is keyed by the requested symbol symbolChanges[packet.Configuration.Symbol] = symbolChange; } } if (securityUpdate.Count > 0) { // check for 'cash securities' if we found valid update data for this symbol // and we need this data to update cash conversion rates, long term we should // have Cash hold onto it's security, then he can update himself, or rather, just // patch through calls to conversion rate to compue it on the fly using Security.Price if (cashSecurities.Contains(packet.Security.Symbol)) { foreach (var cashKvp in cashBook) { if (cashKvp.Value.SecuritySymbol == packet.Security.Symbol) { var cashUpdates = new List<BaseData> {securityUpdate[securityUpdate.Count - 1]}; cash.Add(new UpdateData<Cash>(cashKvp.Value, packet.Configuration.Type, cashUpdates)); } } } security.Add(new UpdateData<Security>(packet.Security, packet.Configuration.Type, securityUpdate)); } if (consolidatorUpdate.Count > 0) { consolidator.Add(new UpdateData<SubscriptionDataConfig>(packet.Configuration, packet.Configuration.Type, consolidatorUpdate)); } } slice = new Slice(algorithmTime, allDataForAlgorithm, tradeBars, quoteBars, ticks, optionChains, splits, dividends, delistings, symbolChanges, allDataForAlgorithm.Count > 0); return new TimeSlice(utcDateTime, count, slice, data, cash, security, consolidator, custom, changes); }