Exemplo n.º 1
0
        /// <summary>Handle SnR levels added/removed</summary>
        private void HandleSnRLevelsChanging(object sender, ListChgEventArgs <SnRLevel> e)
        {
            switch (e.ChangeType)
            {
            case ListChg.ItemAdded:
            {
                // Watch for changes to the SnRLevel so we can update the DB
                e.Item.PropertyChanged += HandleSnRLevelChanged;
                HandleSnRLevelChanged(e.Item);
                break;
            }

            case ListChg.ItemRemoved:
            {
                // Stop watching for changes
                e.Item.PropertyChanged -= HandleSnRLevelChanged;

                // Remove this level from the db.
                // Note: this isn't called during shutdown because this event handler
                // is removed from the binding source before it is disposed.
                m_db.Execute(SqlExpr.RemoveSnRLevel(), 1, SqlExpr.RemoveSnRLevelParams(e.Item));

                break;
            }
            }
        }
Exemplo n.º 2
0
        private void OnPriceDataUpdated()
        {
            PriceDataUpdated.Raise(this);

            // Write the price data into the db
            if (m_suspend_db_updates == 0 && !Equals(PriceData, PriceData.Default))
            {
                m_db.Execute(SqlExpr.UpdatePriceData(), 1, SqlExpr.UpdatePriceDataParams(PriceData));
            }
        }
Exemplo n.º 3
0
        /// <summary>Handle an individual SnR level being updated</summary>
        private void HandleSnRLevelChanged(object sender, PropertyChangedEventArgs e = null)
        {
            if (m_suspend_db_updates != 0)
            {
                return;
            }

            // Update this SnR level in the db
            var snr = (SnRLevel)sender;

            m_db.Execute(SqlExpr.UpdateSnRLevel(), 1, SqlExpr.UpdateSnRLevelParams(snr));
        }
Exemplo n.º 4
0
        public Instrument(MainModel model, string symbol)
        {
            m_cache = new List <Candle>(CacheSize);

            Model               = model;
            SymbolCode          = symbol;
            SupportResistLevels = new BindingSource <SnRLevel> {
                DataSource = new BindingListEx <SnRLevel>()
            };

            // Load the sqlite database of historic price data
            m_db = new Sqlite.Database(DBFilepath);

            // Tweak some DB settings for performance
            m_db.Execute(Sqlite.Sql("PRAGMA synchronous = OFF"));
            m_db.Execute(Sqlite.Sql("PRAGMA journal_mode = MEMORY"));

            // Create a table for the price data info
            m_db.Execute(SqlExpr.PriceDataTable());

            // Ensure tables exist for each of the time frames.
            // Note: timestamp is not the row id. Row Ids should not have any
            // meaning. It's more efficient to let the DB do the sorting
            // and just use 'order by' in queries
            foreach (var tf in Enum <ETimeFrame> .Values.Where(x => x != ETimeFrame.None))
            {
                m_db.Execute(SqlExpr.CandleTable(tf));
            }

            // Create a table for the SnR levels
            m_db.Execute(SqlExpr.SnRLevelsTable());

            // Initialise from the DB, so don't write back to the db
            using (Scope.Create(() => ++ m_suspend_db_updates, () => -- m_suspend_db_updates))
            {
                // Select the default time frame to begin with
                TimeFrame = Settings.General.DefaultTimeFrame;

                // Load the last known price data for the instrument
                PriceData = m_db.EnumRows <PriceData>(SqlExpr.GetPriceData()).FirstOrDefault() ?? new PriceData();

                // Load the known support and resistance levels
                SupportResistLevels.AddRange(m_db.EnumRows <SnRLevel>(SqlExpr.GetSnRLevelData()));

                // Set up the EMAs
                ResetEma();
            }
        }
Exemplo n.º 5
0
        /// <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));
        }
Exemplo n.º 6
0
        /// <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));
        }