QuantConnect / Lean

Lean Algorithmic Trading Engine by QuantConnect (Python, C#)
https://lean.io
Apache License 2.0
9.96k stars 3.29k forks source link

Indicator Resolution.DAILY and timedelta(days=1) gives different values #8416

Open alexschwantes opened 1 week ago

alexschwantes commented 1 week ago

When the symbol resolution is set to Hour, indicator values using Daily resolution are different from indicators using timedelta(days=1)

Expected Behavior

With a symbol resolution of Hour, indicators of resolution.Daily are the same as timedelta(days=1).

Actual Behavior

values are different. Spot the difference between the two graphs:

resolution bug

When the symbol resolution is set to the same as the indicators ie. Resolution.DAILY, the graphs produced are the same. However they are different to the daily resolution graphs above ... history bug 3

Potential Solution

Reproducing the Problem

class TestWarmUp(QCAlgorithm):
    def initialize(self):
        # change the start date between runs to check that warm up shows the correct value
        self.set_start_date(2024, 6, 1)
        self.set_end_date(2024, 7, 1)
        self.set_cash(100000)

        self.spy = self.add_equity("SPY", Resolution.HOUR).symbol

        # Resolution.DAILY indicators
        self._rsi = RelativeStrengthIndex(14, MovingAverageType.WILDERS)
        self._sto = Stochastic(14, 3, 3)
        self.register_indicator(self.spy, self._rsi, Resolution.DAILY)
        self.register_indicator(self.spy, self._sto, Resolution.DAILY)

        # Resolution.DAILY indicators
        self._rsi_timedelta = RelativeStrengthIndex(14, MovingAverageType.WILDERS)
        self._sto_timedelta = Stochastic(14, 3, 3)
        self.register_indicator(self.spy, self._rsi_timedelta, timedelta(days=1))
        self.register_indicator(self.spy, self._sto_timedelta, timedelta(days=1))

        # warm up indicators
        history = self.history[TradeBar](self.spy, 20, Resolution.DAILY)
        for bar in history:
            self._rsi.update(bar.end_time, bar.close)
            self._sto.update(bar)
            self._rsi_timedelta.update(bar.end_time, bar.close)
            self._sto_timedelta.update(bar)

    def on_data(self, data: Slice):
        if self.is_warming_up:
            return

        if data.contains_key(self.spy):
            chart_name = "Resolution.DAILY"
            self.plot(chart_name, "RSI", self._rsi.current.value)
            self.plot(chart_name, "STO K", self._sto.stoch_k.current.value)
            self.plot(chart_name, "STO D", self._sto.stoch_d.current.value)

            chart_name = "timedelta(days=1)"
            self.plot(chart_name, "RSI", self._rsi_timedelta.current.value)
            self.plot(chart_name, "STO K", self._sto_timedelta.stoch_k.current.value)
            self.plot(chart_name, "STO D", self._sto_timedelta.stoch_d.current.value)

System Information

cloud

Checklist

Martin-Molinero commented 1 week ago

With a symbol resolution of Hour, indicators of resolution.Daily are the same as timedelta(days=1).

Hey! this is because resolution daily will respect daily precise end times (if enabled), while a time span will respect the given span

alexschwantes commented 5 days ago

Hi @Martin-Molinero, Yes I have read this before, however it's still not totally clear how they add up, shouldn't timedelat of 1 day still encompass a trading day, assuming that it starts at the same time as the resolution.daily?

However, I think there is more going on here than that.

The second picture in the initial post shows where the symbol is subscribed at a Daily resolution, and the indicators shown are Daily and timedelta. Both these charts are identical which is nice. For me, this graph represents the truth.

However, with the first picture, when the symbol is set to an Hourly resolution, neither the Daily resolution or the timedelta indicator charts come close to matching the 'truth' chart. In fact it almost looks like the timedelta chart is closer to the actual truth.

Here is an updated first picture that shows reporting just once a day to remove the flat parts from the initial code that reported every hour. Notice that it still doesn't look the same as the 'Truth' charts... Even the first values for the STO are wildly off..

image