public void EntrySignal(QuoteBars data, Rule signal) { if (verbose && signal.IsTrue()) { Log(string.Format("signal symbol:: {0}", signal.Symbol)); } if (!Portfolio[signal.Symbol].Invested) { if (signal.IsTrue()) { var openPrice = Securities[signal.Symbol].Price; var entryValues = RiskManager.CalculateEntryOrders(data, signal.Symbol, AgentAction.GoLong); if (entryValues.Item1 != 0) { tookPartialProfit[signal.Symbol] = false; var ticket = MarketOrder(signal.Symbol, entryValues.Item1); StopMarketOrder(signal.Symbol, -entryValues.Item1, entryValues.Item2, tag: entryValues.Item3.ToString("0.000000")); if (verbose) { Log(string.Format("MarketOrder:: {0} {1}", signal.Symbol, entryValues.Item1)); } } //MarketOrder(signal.Symbol, size, false, ""); } } }
public void OnData(QuoteBars data) { long l = (30 * 24 * 60 * 60); long le = (10 * 24 * 60 * 60); foreach (var rule in trades) { if (data.ContainsKey(rule.Symbol)) { var candleStartTime = Utils.ToUnixTimestamp(data[rule.Symbol].Time.ConvertToUtc(Securities[rule.Symbol].Exchange.TimeZone)); var candleEndTime = Utils.ToUnixTimestamp(data[rule.Symbol].EndTime.ConvertToUtc(Securities[rule.Symbol].Exchange.TimeZone)); if (candleStartTime > (rule.setupTime - l) && (candleStartTime < Math.Max(rule.exitTime, rule.expirationTime) + le)) { rule.Serie.Add(new LocalQuote { date = Utils.ToUnixTimestamp(data[rule.Symbol].Time.ConvertToUtc(Securities[rule.Symbol].Exchange.TimeZone)), open = data[rule.Symbol].Open, close = data[rule.Symbol].Close, high = data[rule.Symbol].High, low = data[rule.Symbol].Low }); } } } }
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); }
public void OnData(QuoteBars data) { long l = (30 * 24 * 60 * 60); long le = (10 * 24 * 60 * 60); foreach (var rule in trades) { if (data.ContainsKey(rule.Symbol)) { var candleStartTime = Utils.ToUnixTimestamp(data[rule.Symbol].Time.ConvertToUtc(Securities[rule.Symbol].Exchange.TimeZone)); var candleEndTime = Utils.ToUnixTimestamp(data[rule.Symbol].EndTime.ConvertToUtc(Securities[rule.Symbol].Exchange.TimeZone)); if ((rule._Serie.Count == 0 && (rule.setupTime - l) > candleStartTime) || (rule._Serie.Count > 0 && (rule.exitTime + le > candleStartTime || rule.expirationTime + le > candleStartTime))) { List <LocalQuote> serie = new List <LocalQuote>(); rule._Serie.Add(new LocalQuote { date = Utils.ToUnixTimestamp(data[rule.Symbol].Time.ConvertToUtc(Securities[rule.Symbol].Exchange.TimeZone)), open = data[rule.Symbol].Open, close = data[rule.Symbol].Close, high = data[rule.Symbol].High, low = data[rule.Symbol].Low }); } } } }
/// <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 void AccessesTradeBarAndQuoteBarForSameSymbol() { var tradeBar = new TradeBar(DateTime.Now, Symbols.BTCUSD, 3000, 3000, 3000, 3000, 100, Time.OneMinute); var quoteBar = new QuoteBar(DateTime.Now, Symbols.BTCUSD, new Bar(3100, 3100, 3100, 3100), 0, new Bar(3101, 3101, 3101, 3101), 0, Time.OneMinute); var tradeBars = new TradeBars { { Symbols.BTCUSD, tradeBar } }; var quoteBars = new QuoteBars { { Symbols.BTCUSD, quoteBar } }; var slice = new Slice(DateTime.Now, new BaseData[] { tradeBar, quoteBar }, tradeBars, quoteBars, null, null, null, null, null, null, null); var tradeBarData = slice.Get<TradeBar>(); Assert.AreEqual(1, tradeBarData.Count); Assert.AreEqual(3000, tradeBarData[Symbols.BTCUSD].Close); var quoteBarData = slice.Get<QuoteBar>(); Assert.AreEqual(1, quoteBarData.Count); Assert.AreEqual(3100, quoteBarData[Symbols.BTCUSD].Bid.Close); Assert.AreEqual(3101, quoteBarData[Symbols.BTCUSD].Ask.Close); slice = new Slice(DateTime.Now, new BaseData[] { tradeBar, quoteBar }); tradeBarData = slice.Get<TradeBar>(); Assert.AreEqual(1, tradeBarData.Count); Assert.AreEqual(3000, tradeBarData[Symbols.BTCUSD].Close); quoteBarData = slice.Get<QuoteBar>(); Assert.AreEqual(1, quoteBarData.Count); Assert.AreEqual(3100, quoteBarData[Symbols.BTCUSD].Bid.Close); Assert.AreEqual(3101, quoteBarData[Symbols.BTCUSD].Ask.Close); }
public void OnData(QuoteBars data) { try { foreach (var symbol in Symbols.Where(s => data.ContainsKey(s))) { _tradingAssets[symbol].Scan(data[symbol], ((AverageTrueRangeVolatilityModel)Securities[symbol].VolatilityModel).IsWarmingUp); } } catch (Exception ex) { Log("Error: " + ex.Message); } }
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); }
public void OnData(QuoteBars data) { if (!Portfolio.HoldStock) { SetHoldings("EURUSD", 10); } lastOpenPrice = data["EURUSD"].Open; lastClosePrice = data["EURUSD"].Close; Plot("Trade Plot", "Open", lastOpenPrice); Plot("Trade Plot", "Close", lastClosePrice); if (EMASlow.IsReady) { Plot("Trade Plot", "FastMA", EMAFast); Plot("Trade Plot", "SlowMA", EMASlow); } }
public void OnData(QuoteBars data) { foreach (var entry in _entry) { if (entry.IsReady()) { EntrySignal(data, entry); } } foreach (var entry in _exit) { if (entry.IsReady()) { ExitSignal(entry); } } RiskManager.UpdateTrailingStopOrders(data); }
/// <summary> /// Calculates the entry orders and stop-loss price. /// </summary> /// <param name="pair">The Forex pair Symbol.</param> /// <param name="action">The order direction.</param> /// <returns>a Tuple with the quantity as Item1 and the stop-loss price as Item2. If quantity is zero, then means that no trade must be done.</returns> public Tuple <int, decimal, decimal> CalculateEntryOrders(QuoteBars data, Symbol pair, AgentAction action) { // If exposure is greater than the max exposure, then return zero. if (_portfolio.TotalMarginUsed > _portfolio.TotalPortfolioValue * _maxExposure) { return(Tuple.Create(0, 0m, 0m)); } var closePrice = _portfolio.Securities[pair].Price; var leverage = _portfolio.Securities[pair].Leverage; var exchangeRate = _portfolio.Securities[pair].QuoteCurrency.ConversionRate; var volatility = _portfolio.Securities[pair].VolatilityModel.Volatility; // Estimate the maximum entry order quantity given the risk per trade. var moneyAtRisk = _portfolio.TotalPortfolioValue * _riskPerTrade; var quantity = action == AgentAction.GoLong ? _lotSize : -_lotSize; if ((volatility * exchangeRate) > 0) { var maxQuantitybyRisk = moneyAtRisk / (volatility * exchangeRate); // Estimate the maximum entry order quantity given the exposure per trade. var maxBuySize = Math.Min(_portfolio.MarginRemaining, _portfolio.TotalPortfolioValue * _maxExposurePerTrade) * leverage; var maxQuantitybyExposure = maxBuySize / (closePrice * exchangeRate); // The final quantity is the lowest of both. quantity = (int)(Math.Round(Math.Min(maxQuantitybyRisk, maxQuantitybyExposure) / _lotSize, 0) * _lotSize); // If the final quantity is lower than the minimum quantity of the given lot size, then return zero. if (quantity < _lotSize * _minQuantity) { return(Tuple.Create(0, 0m, 0m)); } quantity = action == AgentAction.GoLong ? quantity : -quantity; } var stopLossPrice = closePrice + (action == AgentAction.GoLong ? -volatility : volatility); var increment = _portfolio.Securities[pair].PriceVariationModel.GetMinimumPriceVariation(_portfolio.Securities[pair]); if (increment != 0) { stopLossPrice = Math.Round(stopLossPrice / increment) * increment; } return(Tuple.Create(quantity, stopLossPrice, action == AgentAction.GoLong ? data[pair].Ask.Close : data[pair].Bid.Close)); }
/// <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> /// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here. /// </summary> /// <param name="data">TradeBars IDictionary object with your stock data</param> public void OnData(QuoteBars data) { SetHoldings(_symbol, 1); return; // only once per day if (_previous.Date == Time.Date) { return; } if (!_macd.IsReady) { return; } var holding = Portfolio[_symbol]; var signalDeltaPercent = (_macd - _macd.Signal) / _macd.Fast; var tolerance = 0.00025m; // if our macd is greater than our signal, then let's go long if (holding.Quantity <= 0 && signalDeltaPercent > tolerance) // 0.01% { // longterm says buy as well SetHoldings(_symbol, 1.0); } // of our macd is less than our signal, then let's go short else if (holding.Quantity >= 0 && signalDeltaPercent < -tolerance) { Liquidate(_symbol); } // plot both lines Plot("MACD", _macd, _macd.Signal); Plot(_symbol, "Open", data[_symbol].Open); Plot(_symbol, _macd.Fast, _macd.Slow); _previous = Time; }
/// <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> /// Adds the specified <see cref="BaseData"/> instance to the appropriate <see cref="DataDictionary{T}"/> /// </summary> private static void PopulateDataDictionaries(BaseData baseData, Ticks ticks, TradeBars tradeBars, QuoteBars quoteBars, OptionChains optionChains, FuturesChains futuresChains) { var symbol = baseData.Symbol; // populate data dictionaries switch (baseData.DataType) { case MarketDataType.Tick: ticks.Add(symbol, (Tick)baseData); break; case MarketDataType.TradeBar: tradeBars[symbol] = (TradeBar)baseData; break; case MarketDataType.QuoteBar: quoteBars[symbol] = (QuoteBar)baseData; break; case MarketDataType.OptionChain: optionChains[symbol] = (OptionChain)baseData; break; case MarketDataType.FuturesChain: futuresChains[symbol] = (FuturesChain)baseData; break; } }
/// <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> /// 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)); }
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> /// Adds the specified <see cref="BaseData"/> instance to the appropriate <see cref="DataDictionary{T}"/> /// </summary> private static void PopulateDataDictionaries(BaseData baseData, Ticks ticks, TradeBars tradeBars, QuoteBars quoteBars, OptionChains optionChains) { var symbol = baseData.Symbol; // populate data dictionaries switch (baseData.DataType) { case MarketDataType.Tick: ticks.Add(symbol, (Tick)baseData); break; case MarketDataType.TradeBar: tradeBars[symbol] = (TradeBar) baseData; break; case MarketDataType.QuoteBar: quoteBars[symbol] = (QuoteBar) baseData; break; case MarketDataType.OptionChain: optionChains[symbol] = (OptionChain) baseData; break; } }
/// <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); }
public void OnData(QuoteBars data) { }
/// <summary> /// Updates the stop-loss price of all open StopMarketOrders. /// </summary> public void UpdateTrailingStopOrders(QuoteBars data) { // Get all the spot-loss orders. var openStopLossOrders = _portfolio.Transactions.GetOrderTickets(o => o.OrderType == OrderType.StopMarket && o.Status == OrderStatus.Submitted); foreach (var ticket in openStopLossOrders) { var stopLossPrice = ticket.SubmitRequest.StopPrice; var volatility = _portfolio.Securities[ticket.Symbol].VolatilityModel.Volatility; var actualPrice = _portfolio.Securities[ticket.Symbol].Price; // The StopLossOrder has the opposite direction of the original order. var originalOrderDirection = ticket.Quantity > 0 ? OrderDirection.Sell : OrderDirection.Buy; if (originalOrderDirection == OrderDirection.Sell) { actualPrice = data[ticket.Symbol].Ask.Close; } if (originalOrderDirection == OrderDirection.Buy) { actualPrice = data[ticket.Symbol].Bid.Close; } var newStopLossPrice = actualPrice + (volatility * (originalOrderDirection == OrderDirection.Buy ? -1 : 1)); var increment = _portfolio.Securities[ticket.Symbol].PriceVariationModel.GetMinimumPriceVariation(_portfolio.Securities[ticket.Symbol]); if (increment != 0) { newStopLossPrice = Math.Round(newStopLossPrice / increment) * increment; } if ((originalOrderDirection == OrderDirection.Buy && newStopLossPrice > stopLossPrice) || (originalOrderDirection == OrderDirection.Sell && newStopLossPrice < stopLossPrice)) { /* * if (originalOrderDirection == OrderDirection.Sell && data[ticket.Symbol].Ask.Close < System.Convert.ToDecimal(ticket.SubmitRequest.Tag)) * { * if(newStopLossPrice>System.Convert.ToDecimal(ticket.SubmitRequest.Tag)) * { * newStopLossPrice = System.Convert.ToDecimal(ticket.SubmitRequest.Tag); * } * } * if (originalOrderDirection == OrderDirection.Buy && data[ticket.Symbol].Bid.Close > System.Convert.ToDecimal(ticket.SubmitRequest.Tag)) * { * //price is on right direction * if(newStopLossPrice<System.Convert.ToDecimal(ticket.SubmitRequest.Tag)) * { * newStopLossPrice = System.Convert.ToDecimal(ticket.SubmitRequest.Tag); * } * } */ ticket.Update(new UpdateOrderFields { Quantity = -(_portfolio[ticket.Symbol].Quantity), StopPrice = newStopLossPrice }); } else if (!_portfolio[ticket.Symbol].Invested) { ticket.Cancel(); } else if (Math.Abs(_portfolio[ticket.Symbol].Quantity) != Math.Abs(ticket.Quantity)) { ticket.Update(new UpdateOrderFields { Quantity = -(_portfolio[ticket.Symbol].Quantity) }); } } }
/// <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> /// <param name="universeData"></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, Dictionary <Universe, BaseDataCollection> universeData) { 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 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(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); 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.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, optionUnderlyingUpdates)) { 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); // option underlying security update if (packet.Security.Symbol.SecurityType == SecurityType.Equity) { optionUnderlyingUpdates[packet.Security.Symbol] = 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) { 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, security, consolidator, custom, changes, universeData)); }