Beispiel #1
0
        /// <summary>Called when a new user account has been assigned</summary>
        private void HandleAcctChanged(object sender = null, EventArgs e = null)
        {
            // Ensure closed
            Util.Dispose(ref m_db);

            // If there is no account id, don't open a database
            if (Model == null || !Model.Acct.AccountId.HasValue())
            {
                return;
            }

            // Open a database of the trade history and other user account related info
            var filepath = Path_.CombinePath(Settings.General.AcctDataCacheDir, "Acct_{0}.db".Fmt(Model.Acct.AccountId));

            m_db = new Sqlite.Database(filepath);

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

            // Ensure the table of trades exists
            var sql = Sqlite.Sql("create table if not exists ", Table.TradeHistory, " (\n",
                                 "[", nameof(Trade.Id), "] text primary key,\n",
                                 "[", nameof(Trade.SymbolCode), "] text)");

            m_db.Execute(sql);

            // Ensure the table of orders exists
            sql = Sqlite.Sql("create table if not exists ", Table.Orders, " (\n",
                             "[", nameof(Order.Id), "] integer primary key,\n",
                             "[", ("TradeId"), "] text,\n",
                             "[", nameof(Order.SymbolCode), "] text,\n",
                             "[", nameof(Order.TradeType), "] integer)");
            m_db.Execute(sql);
        }
Beispiel #2
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();
            }
        }
Beispiel #3
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));
        }