Esempio n. 1
0
        public Candle SubCandle(DateTimeOffset now, ETimeFrame time_frame)
        {
            // Interpolate the latest candle to determine the spot price
            var t = Math_.Frac(Timestamp, now.Ticks, Timestamp + Misc.TimeFrameToTicks(1.0, time_frame));

            return(SubCandle(Math_.Clamp(t, 0.0, 1.0)));
        }
Esempio n. 2
0
        /// <summary>
        /// Emulate the behaviour of the update thread by notifying of
        /// 'DataChanged' as the simulation time advances.</summary>
        public void SimulationUpdate(bool force_invalidate)
        {
            // Don't actually modify the DB.
            var now = Model.UtcNow.Ticks;

            // Determine the update type by comparing the sim time to the time stamp of the current candle.
            // This is a "new" candle the sim time is within one TimeFrame period after the current candle.
            // This is an update to the "latest" candle if within a TimeFrame period of the current candle.
            // Otherwise it's an unknown range.
            var tf_ticks    = Misc.TimeFrameToTicks(1.0, TimeFrame);
            var update_type =
                m_current == null || force_invalidate ? DataEventArgs.EUpdateType.Range :
                now.Within(m_current.Timestamp + 1 * tf_ticks, m_current.Timestamp + 2 * tf_ticks) ? DataEventArgs.EUpdateType.New :
                now.Within(m_current.Timestamp, m_current.Timestamp + 1 * tf_ticks) ? DataEventArgs.EUpdateType.Current :
                DataEventArgs.EUpdateType.Range;

            // Record the last time data was received
            LastUpdatedUTC = Model.UtcNow;

            // Update/Invalidate cached values
            switch (update_type)
            {
            case DataEventArgs.EUpdateType.New:
            {
                // Invalidate 'm_current' so that the next candle is read from the DB.
                // Don't change m_total, m_newest, or m_oldest, they are constant during simulations.
                m_current = null;
                var count = CountTo(now);
                OnDataChanged(new DataEventArgs(update_type, this, new RangeI(count - 1, count), Current));
                break;
            }

            case DataEventArgs.EUpdateType.Current:
            {
                // Nothing to invalidate. 'Current' does sub candle interpolation in back-testing mode.
                var count = CountTo(now);
                OnDataChanged(new DataEventArgs(update_type, this, new RangeI(count - 1, count), Current));
                break;
            }

            default:
            {
                // 'now' has moved to an unknown time. Just invalidate 'm_current'
                m_current = CurrentAt(now);
                OnDataChanged(new DataEventArgs(this));
                break;
            }
            }
        }
Esempio n. 3
0
        /// <summary>Returns the age of this candle as a normalised fraction of the time frame</summary>
        public double Age(Instrument instr)
        {
            var one       = Misc.TimeFrameToTicks(1.0, instr.TimeFrame);
            var age_ticks = Model.UtcNow.Ticks - Timestamp;

            if (age_ticks < 0)
            {
                return(0.0);
            }
            if (age_ticks > one)
            {
                return(1.0);
            }
            return(Math_.Frac(0.0, age_ticks, one));
        }
Esempio n. 4
0
        /// <summary>Add a candle value to the database</summary>
        private void Add(ETimeFrame tf, Candle candle)
        {
            // Sanity check
            Debug.Assert(candle.Valid());
            Debug.Assert(candle.Timestamp != 0);
            Debug.Assert(tf != ETimeFrame.None);
            Debug.Assert(tf == TimeFrame);
            if (Model.BackTesting)
            {
                throw new Exception("Should not be adding candles to the DB while back testing");
            }

            // This is a new candle if it's time stamp is one TimeFrame period after the Newest candle.
            // This is an update to the latest candle if within a TimeFrame period of the Newest candle.
            // Otherwise it's an unknown range.
            var tf_ticks    = Misc.TimeFrameToTicks(1.0, TimeFrame);
            var update_type =
                Newest == null ? DataEventArgs.EUpdateType.Range :
                candle.Timestamp == Newest.Timestamp + tf_ticks ? DataEventArgs.EUpdateType.New :
                candle.Timestamp.Within(Newest.Timestamp, Newest.Timestamp + tf_ticks) ? DataEventArgs.EUpdateType.Current :
                DataEventArgs.EUpdateType.Range;

            // Insert the candle into the database
            UpsertCandle(candle);

            // Record the last time data was received
            LastUpdatedUTC = Model.UtcNow;

            // Update/Invalidate cached values
            switch (update_type)
            {
            case DataEventArgs.EUpdateType.New:
            {
                m_newest  = candle;
                m_current = m_newest;
                m_total  += 1;
                break;
            }

            case DataEventArgs.EUpdateType.Current:
            {
                m_newest.Update(candle);
                m_current = m_newest;
                break;
            }

            default:
            {
                // This must be an update to some random candle in the middle.
                // Just invalidate the cached values. Shouldn't ever happen really.
                m_total   = null;
                m_newest  = null;
                m_oldest  = null;
                m_current = null;
                break;
            }
            }

            // Notify data added/changed
            OnDataChanged(new DataEventArgs(update_type, this, new RangeI(Count - 1, Count), candle));
        }
Esempio n. 5
0
 public TimeFrameTime(double tf_units, ETimeFrame tf)
     : this(Misc.TimeFrameToTicks(tf_units, tf), tf)
 {
 }