/// <summary>Add a batch of candles</summary> public void Add(ETimeFrame tf, PriceCandles candles) { // Insert the candles into the database using (var t = m_db.NewTransaction()) using (var query = new Sqlite.Query(m_db, SqlExpr.InsertCandle(tf))) { foreach (var candle in candles.AllCandles.Select(x => new Candle(x))) { query.Reset(); query.BindParms(1, SqlExpr.InsertCandleParams(candle)); query.Run(); } t.Commit(); } // Don't bother maintaining the cache, just invalidate it InvalidateCachedData(); // Record the last time data was received LastUpdatedUTC = Model.UtcNow; // Notify data added/changed DataChanged.Raise(this, new DataEventArgs(this, tf, null, false)); }
/// <summary>Add a candle value to the data</summary> public void Add(ETimeFrame tf, PriceCandle price_candle) { // Sanity check var candle = new Candle(price_candle); Debug.Assert(candle.Valid()); Debug.Assert(candle.Timestamp != 0); Debug.Assert(tf != ETimeFrame.None); // If this candle is the newest we've seen, then a new candle has started. // Get the latest candle before inserting 'candle' into the database var new_candle = tf == TimeFrame && candle.Timestamp > Latest.Timestamp; // Insert the candle into the database if the sim isn't running. // The sim draws it's data from the database, so there's no point in writing // the same data back in. Plus it might in the future do things to emulate sub-candle // updates, which I don't want to overwrite the actual data. if (!Model.SimActive) { m_db.Execute(SqlExpr.InsertCandle(tf), 1, SqlExpr.InsertCandleParams(candle)); } // If the candle is for the current time frame and within the // cached data range, update the cache to avoid invalidating it. if (tf == TimeFrame) { // Within the currently cached data? // Note: this is false if 'candle' is the start of a new candle if (!new_candle) { // Find the index in the cache for 'candle'. If not an existing cache item, then just reset the cache var cache_idx = m_cache.BinarySearch(x => x.Timestamp.CompareTo(candle.Timestamp)); if (cache_idx >= 0) { m_cache[cache_idx].Update(candle); } else { InvalidateCachedData(); } } // If the cached range ends at the latest candle (excluding the new candle) // then we can preserve the cache and append the new candle to the cache data else if (m_index_range.Endi == Count) { // If adding 'candle' will make the cache too big, just flush if (m_cache.Count > MaxCacheSize) { InvalidateCachedData(); } // Otherwise, append the new candle to the cache else { m_cache.Add(candle); m_index_range.End++; m_impl_count = null; m_impl_total = null; m_latest = null; } } // Otherwise the candle is not within the cache, just invalidate else { InvalidateCachedData(); } } // Record the last time data was received LastUpdatedUTC = Model.UtcNow; // Notify data added/changed OnDataChanged(new DataEventArgs(this, tf, candle, new_candle)); }