Reprint need to indicate source: http://blog.csdn.net/minimicall,http://cloudtrade.top
We previously explained the data reader, data slots. Data is read into the queue, and the datafeed thread's data is used in the main thread of the algorithm. This is a typical reader--writing a question.
In the main thread and datafeed to play the teaching thing datastream. Let's look at its code. The description is described in the note.
/* * Quantconnect.com-democratizing Finance, empowering individuals. * Lean Algorithmic Trading Engine v2.0. Copyright Quantconnect Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * You are not a use this file except in compliance with the License. * Obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * unless required by applicable l AW or agreed to writing, software * Distributed under the License are distributed on a "as is" BASIS, * without WARRANT IES or CONDITIONS of any KIND, either express OR implied. * See the License for the specific language governing permissions and * limitations under the License. **/using system;using system.collections.generic;using system.threading;using system.diagnostics;using System.Linq; Using quantconnect.data;using quantconnect.lean.engine.datafeeds;using Quantconnect.logging;namespace quantconnect.lean.engine{/******************************************************** * Quantconnect namespaces *********************************************************///<summary>//Da Ta Stream class takes a datafeed hander and converts it into a synchronized enumerable data format for looping//Data flow Class, which has a data slot handle, and then converts the data into a synchronous enumerable, which is used as a loop. In the primary algorithm thread. </summary> public static class DataStream {/****************************************************** * * CLASS VARIABLES *********************************************************///count of Bridges A nd subscriptions. The number of subscriptions is the number of securities added by addsecurity private static int _subscriptions; /******************************************************** * CLASS PROPERTIES ****************************** ////<summary>//The frontier time of the data stream// </summary> public static DateTime algorithmtime {get; private set;} /******************************************************** * CLASS METHODS ******************************* ////<summary>//Process over the Datafeed cross thread bridges to genera Te an enumerable sorted collection of the data, ready for a consumer//to use and already synchronized in time. </summary>//<param name= "feed" >datafeed object</param>//<param name= "f Rontierorigin ">starting date for the data feed</param>//<returns></returns> public s Tatic Ienumerable<dictionary<int, list<basedata>>> GetData (idatafeed feed, DateTime frontierorigin {//initialize: _subscriptions = feed. subscriptions.count;//number of securities subscribed Algorithmtime = frontierorigin;//algorithm pre-time long algorithmtime = algorithm time.ticks;//get time tick var frontier = Frontierorigin; var nexteMittime = Datetime.minvalue; var periods = feed. Subscriptions.select (x = X.resolution.totimespan ()). ToArray (); Wait for datafeeds to is ready, and wait for first data to arrive:while (feed. Bridge.length! = _subscriptions) thread.sleep (100); Clear data first when on Live mode, start with fresh data if (Engine.livemode) {f Eed. Purgedata (); }//get all data in Queues:return as a sorted dictionary://Gets all the information in the queue and returns the in-order dictionary to the while ( !feed. Endofbridges) {//reset items which is not fill forward:long earlybirdticks = 0 ; var newdata = new Dictionary<int, list<basedata>> (); Spin wait until the feed catches up to our frontier waitfordataorendofbridges (Feed, Frontier); for (var i = 0; i < _subscriptions; i++) {//if thEre ' s data on the bridge, check for see if it's time to pull it off, if it's in the Reco Rd the time as ' earlybirdticks ' so we can fast forward the frontier time while (!feed. Bridge[i]. IsEmpty)//I securities have data {//look at first item on list, leave it there until time PA SSEs this item. Check the first entry in the list list<basedata> result; if (!feed. Bridge[i]. Trypeek (out result)) {//If there ' s no item skip to the next Subscripti On//If the security has no data, then jump directly to the next security break; } if (result. Count > 0 && result[0]. EndTime > Frontier) {//We have at least one item, check to see if I TS in ahead of the frontier,//If so, KEEP track of what many ticks in the future it is if (earlybirdticks = = 0 | | earlybirdticks > Result[0]. Endtime.ticks) {earlybirdticks = result[0]. Endtime.ticks; } break; } if (result. Count > 0) {//We have at least one item, check to see if it in Ahe Ad of the Frontier,//If so, keep track of what many ticks in the if (Earlybirdticks = = 0 | | earlybirdticks > RESULT[0]. Endtime.ticks) {earlybirdticks = result[0]. Endtime.ticks; }}//pull a grouped time list out of the bridge list <BaseData> datapoints; if (feed. Bridge[i]. Trydequeue (out datapoints)) {//round the time off based on the reques Ted resolution for fill forward data//This is a temporary fix, long term fill forward logic s Hould be moved to this class foreach (var. in datapoints) { if (Algorithmtime < point. Endtime.ticks) {//Set this to more advanced end point In time, pre rounding/min 10:02 10:02:01 (FF) 10:02:01.01 (FF) SEC 10:02 10:02:01 10:02:01.01 (FF)//tic 10:02 10:02:01 1 0:02:01.01//The algorithm time should always be the ' frontier ' the furthest Time within this data slice Algorithmtime = point. Endtime.ticks; } if (point. Isfillforward) {point. Time = point. Time.rounddown (Periods[i]); }}//Add the list to the collection-be yielded List<basedata> DP; if (!newdata.trygetvalue (I, out DP)) {DP = new List<basedata > (); Newdata[i] = DP; } DP. AddRange (datapoints); } else {//should never fail: Log.error ("Datastream.getdata (): Failed to Dequeue Bridge item"); } }} if (Newdata.count > 0) {algorithmtime = new Da Tetime (Algorithmtime); Yield return newdata; }//update the frontier and start again. if (Earlybirdticks > 0) {//seek forward in time to next data event from Stream:ther E ' s nothing here for us to do Now:why loop over empty seconds frontier = new DateTime (earlybirdticks); } else if (feed. Endofbridges) {//we ' re out of the data or quit break; }//allow loop pass through emits every second to allow event handling (Liquidate/stop/ect ...) if (Engine.livemode && datetime.now > Nextemittime) {algorithmtime = Dat ETime.Now.RoundDown (periods. Min ()); Nextemittime = DateTime.now + timespan.fromseconds (1); Yield return new Dictionary<int, list<basedata>> (); }} log.trace ("Datastream.getdata (): All Streams completed."); }///<summary>//Waits until the data feed is ready for the data stream to pull data from it. Wait for the data slot ready to pull data from the inside//</summary>//<param name= "feed" >the idatafeed instance Populati ng the bridges</param>///<param name= "Datastreamfrontier" >the frontier of the data STREAM</PARAM&G T private static void Waitfordataorendofbridges (Idatafeed feed, DateTime datastreamfrontier) {//make sure All bridges has data to to peek sync properly. var now = Stopwatch.startnew (); Timeout to prevent infinite looping this--50ms for Live and 30sec for non-live var looptimeout = (engine.l Ivemode)? 50:30,000; if (engine.livemode) {//Give some time to the other threads in Live mode Thread.Sleep (1); }//waiting for data in the Bridges:while (! Allbridgeshavedata (Feed) && now. Elapsedmilliseconds < Looptimeout) {Thread.Sleep (1); }//we want to verify, our data stream was never ahead of our data feed. This acts as a virtual lock around the bridge so we can wait for the feed//to be ahead of us//I F we ' re out of data then the feed would never update (it would stay here forever if there's no more data, so use a timeout!! while (Datastreamfrontier > Feed). Loadeddatafrontier && (!feed. Endofbridges &&!feed. Loadingcomplete) && now. Elapsedmilliseconds < Looptimeout) {Thread.Sleep (1); }}///<summary>//Check If all the bridges has data or ARE dead before starting the analysis//////This determines whether or not the data stream can pull data fr Om the data feed. </summary>//<param name= "feed" >feed Interface with concurrent connection between producer and co Nsumer</param>//<returns>boolean True more data to download</returns> private static Bo Ol Allbridgeshavedata (Idatafeed feed) {//lock on the bridge to scan if it has data:for (var i = 0; i < _subscriptions; i++) {if (feed. Endofbridge[i]) continue; if (feed. Bridge[i]. IsEmpty) {return false; }} return true; }//<summary>//Resets the frontier time to Datetime.minvalue///</summary> P ublic static void Resetfrontier () {algorithmtime = new DateTime (); } }}
Programmer's Quantitative Trading Path (PNS)--lean DataStream data stream 7