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(); } }
public Transmitter(string sym, string db_filepath) { SymbolCode = sym; TimeFrames = new ETimeFrame[0]; // Load the instrument candle database m_db = new Sqlite.Database(db_filepath, Sqlite.OpenFlags.ReadOnly); // Read the price data PriceData = m_db.EnumRows <PriceData>("select * from PriceData").First(); }
/// <summary>Return all the candles in the given time range</summary> public IEnumerable <InMsg.CandleData> EnumCandleData(DateTimeOffset t0, DateTimeOffset t1) { var ts = "[" + nameof(Candle.Timestamp) + "]"; var sql = Str.Build("select * from {0} where ", ts, " >= ? and ", ts, " <= ? order by ", ts); var args = new object[] { t0.Ticks, t1.Ticks }; foreach (var tf in TimeFrames) { foreach (var candle in m_db.EnumRows <Candle>(sql.Fmt(tf), 1, args)) { yield return(new InMsg.CandleData(SymbolCode, tf, candle)); } } }
/// <summary>The raw data. Idx = 0 is the oldest, Idx = Count is the latest</summary> public Candle this[PosIdx pos_idx] { get { Debug.Assert(pos_idx >= 0 && pos_idx < Count); // Shift the cached range if needed if (!m_index_range.Contains(pos_idx)) { m_cache.Clear(); // Otherwise, reload the cache centred on the requested index var new_range = new Range((long)pos_idx - CacheSize / 2, (long)pos_idx + CacheSize / 2); if (new_range.Beg < 0) { new_range = new_range.Shift(0 - new_range.Beg); } if (new_range.End > Count) { new_range = new_range.Shift(Count - new_range.End); } if (new_range.Beg < 0) { new_range.Beg = 0; } // Populate the cache from the database // Order by timestamp so that the oldest is first, and the newest is at the end. var sql = Str.Build("select * from ", TimeFrame, " order by [", nameof(Candle.Timestamp), "] limit ?,?"); m_cache.AddRange(m_db.EnumRows <Candle>(sql, 1, new object[] { new_range.Begi, new_range.Sizei })); m_index_range = new_range; } return(m_cache[(int)pos_idx - m_index_range.Begi]); } }