コード例 #1
0
 public void AddQuoteBasic(IQuoteBasicBase qb, bool isAddToAll, bool isTriggerEvent)
 {
     lock (this)
     {
         if (qb != null && qb.Count > 0 && Intervals.Contains(qb.Interval))
         {
             if (isAddToAll)
             {
                 var index    = this.Intervals.FindIndex(i => i == qb.Interval);
                 var interval = this.Intervals[index];
                 var quoteId  = this.CreateQuote(qb.Symbol, interval);
                 var num      = Quotes[quoteId].Append(qb, isTriggerEvent);                                                    //trigger OnQuoteBasicDataAddedOrUpdated
                 //var num = Quotes[quoteId].Append(qb, false);                                                      //do not trigger OnQuoteBasicDataAddedOrUpdated until we add to all quotes
                 if (num >= 0)
                 {
                     var d = this.AddToOtherQuotes(Quotes[quoteId], index + 1, isTriggerEvent);
                     //QuoteStore_OnDataAddedOrUpdated(this, this.Quotes[quoteId], num);
                     //foreach (var qId in d.Keys) QuoteStore_OnDataAddedOrUpdated(this, this.Quotes[qId], d[qId]);
                 }
             }
             else
             {
                 var quoteId = this.CreateQuote(qb.Symbol, qb.Interval);
                 var num     = Quotes[quoteId].Append(qb, isTriggerEvent);
             }
         }
     }
 }
コード例 #2
0
        public static void SaveToFile(this IQuoteBasicBase quote, string filename)
        {
            var writestream = new FileStream(filename, FileMode.Create);

            quote.AppendStream(writestream);
            writestream.Close();
        }
コード例 #3
0
 void QuoteStore_OnDataAddedOrUpdated(object sender, IQuoteBasicBase qb, int numAppended)
 {
     OnQuoteBasicDataAddedOrUpdated?.Invoke(sender, this.Exchange, qb, numAppended);
     if (qb.Count > MaxNumCandles * 2)
     {
         qb.Clear(0, qb.Count - MaxNumCandles - 1);
     }
 }
コード例 #4
0
        public static IQuoteBasicBase LoadFile(this IQuoteBasicBase quote, string filename)
        {
            var readtream = new FileStream(filename, FileMode.Open);

            quote = QuoteBasicBase.InitByStream(readtream);
            readtream.Close();
            return(quote);
        }
コード例 #5
0
 /// <summary>
 /// 复制IQuoteBasic的内容
 /// </summary>
 /// <param name="q"></param>
 public QuoteBasicBase(IQuoteBasicBase q)
 {
     Symbol   = q.Symbol;
     Interval = q.Interval;
     Time     = new List <long>(q.Time);
     Open     = new List <double>(q.Open);
     Close    = new List <double>(q.Close);
     High     = new List <double>(q.High);
     Low      = new List <double>(q.Low);
     Volume   = new List <double>(q.Volume);
 }
コード例 #6
0
        private Dictionary <string, int> AddToOtherQuotes(IQuoteBasicBase prevQuote, int sindex, bool isTriggerEvent)
        {
            var addedNumber   = new Dictionary <string, int>();
            var originQuoteId = prevQuote.QuoteID;
            var interval      = prevQuote.Interval;

            for (int i = sindex; i < this.Intervals.Count; i++)
            {
                var interv = this.Intervals[i];
                if (interv < interval || interv % interval != 0)
                {
                    continue;
                }

                var quoteId = this.CreateQuote(prevQuote.Symbol, interv);
                var num     = Quotes[quoteId].Append(prevQuote, isTriggerEvent);
                if (num == -1)
                {
                    break;
                }

                addedNumber.Add(quoteId, num);
                prevQuote = Quotes[quoteId];
                interval  = interv;
            }

            var q = this.Quotes[originQuoteId];

            interval = q.Interval;
            for (int i = sindex; i < this.Intervals.Count; i++)
            {
                var interv = this.Intervals[i];
                if (interv <= interval || interv % interval != 0)
                {
                    continue;
                }

                var quoteId = this.CreateQuote(q.Symbol, interv);
                var num     = Quotes[quoteId].Append(q, isTriggerEvent);
                if (num >= 0)
                {
                    if (!addedNumber.ContainsKey(quoteId))
                    {
                        addedNumber.Add(quoteId, 0);
                    }
                    addedNumber[quoteId] += num;
                }
            }
            return(addedNumber);
        }
コード例 #7
0
        private int AddItemByQuoteBasic(IQuoteBasicBase q, int sindex, int eindex)
        {
            var len    = eindex - sindex + 1;
            var open   = q.Open[sindex];
            var close  = q.Close[eindex];
            var high   = q.High.GetRange(sindex, len).Max();
            var low    = q.Low.GetRange(sindex, len).Min();
            var volume = q.Volume.GetRange(sindex, len).Sum();
            var time   = q.Time[sindex] / this.Interval * this.Interval;

            //repeat quote to fill gap
            //FillGap(isFillGap, endTime, ref numAddedElement);
            return(this.AddUpdate(time, open, high, low, close, volume));  //add the data
        }
コード例 #8
0
        //file naming convention: exchange_symbol_interval_index.txt
        public bool Save(IQuoteBasicBase quote, int numBarsToRemoveGap = -1)
        {
            lock (this)
            {
                if (quote == null || quote.Count == 0)
                {
                    return(false);
                }
                var files = this.FindQuoteFiles(quote.Symbol, quote.Interval);

                if (files != null && files.Count > 0)
                {
                    files.Sort();
                    var q1 = QuoteBasicExension.LoadFile(files.Last());

                    if (numBarsToRemoveGap > 0)
                    {
                        for (int i = Math.Max(0, q1.Count - numBarsToRemoveGap); i < q1.Count - 1; i++)
                        {
                            if (q1.Time[i + 1] - q1.Time[i] > q1.Interval)
                            {
                                q1.Clear(i + 1, q1.Count - 1);
                                break;
                            }
                        }
                    }

                    //var readtream = new FileStream(files.Last(), FileMode.Open);
                    //var q1 = QuoteBasicBase.InitByStream(readtream);
                    //readtream.Close();

                    if (quote.LastTime <= q1.LastTime)
                    {
                        return(false);
                    }

                    if (q1.Count < _maxNumBarsInFile)
                    {
                        var fn = files.Last();
                        q1.Append(quote);
                        q1.SaveToFile(fn);
                        //var writestream = new FileStream(files.Last(), FileMode.Truncate);
                        //q1.AppendStream(writestream);
                        //writestream.Close();
                        OnQuoteSaved?.Invoke(this, this.Exchange, fn);
                    }
                    else
                    {
                        var last  = files.Last().Split('_').Last();
                        var index = int.Parse(last.Split('.')[0]);
                        var fn    = this.GetQuoteFileName(quote.Symbol, quote.Interval, index + 1);

                        //var writestream = new FileStream(fn, FileMode.OpenOrCreate);
                        if (q1.LastTime >= quote.FirstTime)  //remove redundant sticks from new files
                        {
                            var sind = quote.FindIndexForGivenTime(q1.LastTime);
                            var q2   = new QuoteBasicBase(quote);
                            q2.Clear(0, sind);
                            q2.SaveToFile(fn);
                            //q2.AppendStream(writestream);
                        }
                        else
                        {
                            quote.SaveToFile(fn);
                            //quote.AppendStream(writestream);
                        }
                        //writestream.Close();
                        OnQuoteSaved?.Invoke(this, this.Exchange, fn);
                    }
                }
                else
                {
                    var fn = this.GetQuoteFileName(quote.Symbol, quote.Interval, 0);
                    quote.SaveToFile(fn);
                    //var writestream = new FileStream(fn, FileMode.OpenOrCreate);
                    //quote.AppendStream(writestream);
                    //writestream.Close();
                    OnQuoteSaved?.Invoke(this, this.Exchange, fn);
                }

                return(true);
            }
        }
コード例 #9
0
        private void _qbStore_OnQuoteBasicDataAddedOrUpdated(object sender, string exchange, IQuoteBasicBase quote, int numAppended)
        {
            OnQuoteBasicDataAddedOrUpated?.Invoke(sender, this.Exchange, quote, numAppended);

            //var j = quote.Count - numAppended;
            //var lst = new List<OHLC>();
            //for (int i = j; i < quote.Count; i++)
            //{
            //    var ohlc = new OHLC
            //    {
            //        Symbol = quote.Symbol,
            //        Interval = quote.Interval,
            //        Time = quote.Time[i],
            //        Open = quote.Open[i],
            //        Close = quote.Close[i],
            //        High = quote.High[i],
            //        Low = quote.Low[i],
            //        Volume = quote.Volume[i]
            //    };
            //    lst.Add(ohlc);
            //}
            //OnCandleListReceived?.Invoke(this, this.Exchange, lst);

            // save quote
            if (!_quoteIdToSave.Contains(quote.QuoteID))
            {
                _quoteIdToSave.Enqueue(quote.QuoteID);
            }

            //var utcnow = DateTime.UtcNow.GetUnixTimeFromUTC();
            //if (!_lastSaveTime.ContainsKey(quote.QuoteID))
            //{
            //    var t = quote.Interval <= 900 ? utcnow + _random.Next(900) : 0;
            //    _lastSaveTime.TryAdd(quote.QuoteID, t);
            //}

            //if (utcnow - _lastSaveTime[quote.QuoteID] > _saveInterval)
            //{
            //    _quoteIdToSave.Enqueue(quote.QuoteID);
            //    _lastSaveTime[quote.QuoteID] = utcnow;
            //}

            //if (_quoteIdToSave.Count > 0)
            //    this.ProcessSaveQuoteBasicQueue();
        }
コード例 #10
0
 private void TestAddEventInternal(object sender, IQuoteBasicBase quote, int numAppended)
 {
     throw new Exception();
 }
コード例 #11
0
        //[0,1,2,4,5)
        public int Append(IQuoteBasicBase q, bool isTriggerDataUpdated = false)
        {
            //no data to add
            if (q == null || q.Count <= 0 || q.LastTime < this.LastTime || this.Symbol != q.Symbol || this.Interval < q.Interval || this.Interval % q.Interval != 0)
            {
                return(0);
            }

            //search backward for quotes to be added. the found time should be >= this.LastTime
            int indexStartSearch = -1;

            for (int i = q.Count - 1; i >= 0; i--)
            {
                if (q.Time[i] < this.LastTime)
                {
                    break;
                }
                indexStartSearch = i;
            }
            if (indexStartSearch == -1)
            {
                return(0);
            }

            /////////////////////////////////////////////////////////////////////////////////
            var numBeforeAdd    = this.Count;
            var isDataChanged   = false;
            var numAddedElement = 0;

            int sindex  = indexStartSearch;                                               // interval区间的开始索引
            var eindex  = -1;
            var endTime = q.Time[sindex] / this.Interval * this.Interval + this.Interval; //use the first time as the data bar time

            for (int i = indexStartSearch; i <= q.Count - 1; i++)
            {
                if (q.Time[i] >= endTime)
                {
                    eindex = i - 1;        // interval区间的结束索引
                    var num = this.AddItemByQuoteBasic(q, sindex, eindex);
                    if (num >= 0)
                    {
                        numAddedElement += num;
                        isDataChanged    = true;
                    }
                    sindex  = i;
                    endTime = q.Time[sindex] / this.Interval * this.Interval + this.Interval;
                }
            }

            //add last element
            if (sindex > eindex)
            {
                var num = this.AddItemByQuoteBasic(q, sindex, q.Count - 1);
                if (num >= 0)
                {
                    numAddedElement += num;
                    isDataChanged    = true;
                }
            }

            if (isTriggerDataUpdated && isDataChanged)
            {
                OnDataAddedOrUpdated?.Invoke(this, this, numAddedElement);
            }

            return(isDataChanged? numAddedElement : -1);  //-1 means nothing changed, 0 means updated, >=1 means added
        }