title: Why pandas EMA result different with manually calculated EMA?
body: <p>I'm trying to compare EMA result between pandas and manually calcaluted.</p>
  <p>Here's the sample code <code>test_pandas.py</code> I'm using:</p>
  <pre><code># -*- coding:utf-8 -*-
  # Copyright 2021-  &lt;linrongbin16@outlook.com&gt;
  
  &quot;&quot;&quot;test pandas&quot;&quot;&quot;
  
  from loguru import logger
  import pandas
  import numpy
  import math
  import datetime
  
  
  def _calculate_mean(data: list[float]) -&gt; float:
      return math.fsum(data) / len(data)
  
  
  def _calculate_sma(data: list[float], n: int) -&gt; list[float]:
      return [_calculate_mean(data[max(0, i + 1 - n) : i + 1]) for i in range(len(data))]
  
  
  def _calculate_ema_impl(data: list[float], alpha: float) -&gt; float:
      n = len(data)
      result = numpy.zeros(n)
      for i in range(len(data)):
          result[i] = data[i] if i == 0 else alpha * data[i] + (1 - alpha) * result[i - 1]
      return result[-1]
  
  
  def _calculate_ema(data: list[float], n: int) -&gt; list[float]:
      alpha = 2 / (n + 1)
      result = [0.0 for _ in range(len(data))]
      for i in range(len(data)):
          result[i] = _calculate_ema_impl(data[max(0, i + 1 - n) : i + 1], alpha)
      return result
  
  
  def _assert_eq(a: list[float], b: list[float]) -&gt; None:
      from quant.common.floatings import eq
  
      assert isinstance(a, list)
      assert isinstance(b, list)
      assert len(a) == len(b)
      for i in range(len(a)):
          assert eq(a[i], b[i])
  
  
  class TestPandas:
      data = {
          &quot;date&quot;: [
              datetime.date(t[0], t[1], t[2])
              for t in [
                  (2021, 10, 1),
                  (2021, 10, 2),
                  (2021, 10, 3),
                  (2021, 10, 4),
                  (2021, 10, 5),
                  (2021, 10, 6),
                  (2021, 10, 6),
                  (2021, 10, 7),
                  (2021, 10, 9),
                  (2021, 10, 10),
                  (2021, 10, 11),
                  (2021, 10, 12),
                  (2021, 10, 13),
                  (2021, 10, 14),
                  (2021, 10, 15),
                  (2021, 10, 16),
                  (2021, 10, 17),
                  (2021, 10, 18),
                  (2021, 10, 19),
                  (2021, 10, 20),
              ]
          ],
          &quot;price&quot;: [
              1.1,
              2.63,
              3.53,
              4.4,
              15.9,
              6.21,
              7.91,
              3.09,
              9.1,
              14.4,
              11.92,
              2.92,
              13.04,
              14.14,
              15.85,
              37.23,
              812.12,
              321.21,
              817.12,
              948.43,
          ],
      }
  
      def test_sma_and_ema(self) -&gt; None:
          df = pandas.DataFrame(TestPandas.data)
          df1 = pandas.DataFrame(
              {
                  &quot;sma10&quot;: df[&quot;price&quot;].rolling(window=10, min_periods=0).mean(),
                  &quot;ema10&quot;: df[&quot;price&quot;].ewm(span=10, min_periods=0, adjust=False).mean(),
              }
          )
          df = pandas.concat([df, df1], axis=1)
          with pandas.option_context(&quot;display.max_rows&quot;, None, &quot;display.max_columns&quot;, None):
              logger.debug(f&quot;df:\n{df}&quot;)
  
          expect_sma10 = _calculate_sma(TestPandas.data[&quot;price&quot;], 10)
          expect_ema10 = _calculate_ema(TestPandas.data[&quot;price&quot;], 10)
          logger.debug(f&quot;expect sma10:\n{expect_sma10}&quot;)
          logger.debug(f&quot;expect ema10:\n{expect_ema10}&quot;)
          _assert_eq(df[&quot;sma10&quot;].tolist(), expect_sma10)
          _assert_eq(df[&quot;ema10&quot;].tolist(), expect_ema10)
  
  </code></pre>
  <p>Running with <code>pytest -s test_pandas.py</code>:</p>
  <pre><code>$ pytest -s test_pandas.py
  ============================================================================================================================ test session starts =============================================================================================================================
  platform darwin -- Python 3.9.9, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
  rootdir: /Users/xxx/workspace/github/xxx
  plugins: anyio-3.2.1
  collected 2 items
  
  
  .2021-11-29 16:24:05.765 | DEBUG    | quant.test.test_pandas:test_sma_and_ema:144 - df:
            date   price       sma10       ema10
  0   2021-10-01    1.10    1.100000    1.100000
  1   2021-10-02    2.63    1.865000    1.378182
  2   2021-10-03    3.53    2.420000    1.769421
  3   2021-10-04    4.40    2.915000    2.247708
  4   2021-10-05   15.90    5.512000    4.729943
  5   2021-10-06    6.21    5.628333    4.999045
  6   2021-10-06    7.91    5.954286    5.528309
  7   2021-10-07    3.09    5.596250    5.084980
  8   2021-10-09    9.10    5.985556    5.814984
  9   2021-10-10   14.40    6.827000    7.375896
  10  2021-10-11   11.92    7.909000    8.202097
  11  2021-10-12    2.92    7.938000    7.241715
  12  2021-10-13   13.04    8.889000    8.295949
  13  2021-10-14   14.14    9.863000    9.358504
  14  2021-10-15   15.85    9.858000   10.538776
  15  2021-10-16   37.23   12.960000   15.391726
  16  2021-10-17  812.12   93.381000  160.251412
  17  2021-10-18  321.21  125.193000  189.516610
  18  2021-10-19  817.12  205.995000  303.626317
  19  2021-10-20  948.43  299.398000  420.863350
  2021-11-29 16:19:35.896 | DEBUG    | quant.test.test_pandas:test_sma_and_ema:158 - expect sma10:
  [1.1, 1.865, 2.42, 2.915, 5.5120000000000005, 5.628333333333334, 5.954285714285715, 5.59625, 5.985555555555555, 6.827, 7.909000000000001, 7.938, 8.889, 9.863, 9.858, 12.959999999999999, 93.381, 125.19300000000001, 205.99499999999998, 299.398]
  2021-11-29 16:19:35.896 | DEBUG    | quant.test.test_pandas:test_sma_and_ema:159 - expect ema10:
  [1.1, 1.3781818181818182, 1.7694214876033056, 2.24770848985725, 4.729943309883205, 4.999044526268077, 5.528309157855699, 5.084980220063754, 5.814983816415798, 7.375895849794744, 8.407775472483964, 7.5309856833248965, 8.649579300484998, 11.19378988610481, 10.737740711835833, 15.78304720353951, 159.92362842577154, 190.0563513602728, 304.78040619379453, 421.4742170984318]
  F
  
  ================================================================================================================================== FAILURES ==================================================================================================================================
  ________________________________________________________________________________________________________________________ TestPandas.test_sma_and_ema _________________________________________________________________________________________________________________________
  
  self = &lt;quant.test.test_pandas.TestPandas object at 0x123a0df70&gt;
  
      def test_sma_and_ema(self) -&gt; None:
          df = pandas.DataFrame(TestPandas.data)
          df1 = pandas.DataFrame(
              {
                  &quot;sma10&quot;: df[&quot;price&quot;].rolling(window=10, min_periods=0).mean(),
                  &quot;sma_std10&quot;: df[&quot;price&quot;].rolling(window=10, min_periods=0).std(),
                  &quot;ema10&quot;: df[&quot;price&quot;].ewm(span=10, min_periods=0, adjust=False).mean(),
                  &quot;ema_std10&quot;: df[&quot;price&quot;].ewm(span=10, min_periods=0, adjust=False).std(),
              }
          )
          df2 = pandas.DataFrame(
              {
                  &quot;boll_low_sma10&quot;: df1[&quot;sma10&quot;] - df1[&quot;sma_std10&quot;] * 2,
                  &quot;boll_up_sma10&quot;: df1[&quot;sma10&quot;] + df1[&quot;sma_std10&quot;] * 2,
                  &quot;boll_low_ema10&quot;: df1[&quot;ema10&quot;] - df1[&quot;ema_std10&quot;] * 2,
                  &quot;boll_up_ema10&quot;: df1[&quot;ema10&quot;] + df1[&quot;ema_std10&quot;] * 2,
              }
          )
          df = pandas.concat([df, df1, df2], axis=1)
          with pandas.option_context(&quot;display.max_rows&quot;, None, &quot;display.max_columns&quot;, None):
              logger.debug(f&quot;df:\n{df}&quot;)
  
          expect_sma10 = _calculate_sma(TestPandas.data[&quot;price&quot;], 10)
          expect_ema10 = _calculate_ema(TestPandas.data[&quot;price&quot;], 10)
          logger.debug(f&quot;expect sma10:\n{expect_sma10}&quot;)
          logger.debug(f&quot;expect ema10:\n{expect_ema10}&quot;)
          _assert_eq(df[&quot;sma10&quot;].tolist(), expect_sma10)
  &gt;       _assert_eq(df[&quot;ema10&quot;].tolist(), expect_ema10)
  
  quant/test/test_pandas.py:161:
  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
  
  a = [1.1, 1.3781818181818182, 1.7694214876033056, 2.24770848985725, 4.729943309883205, 4.999044526268077, ...], b = [1.1, 1.3781818181818182, 1.7694214876033056, 2.24770848985725, 4.729943309883205, 4.999044526268077, ...]
  
      def _assert_eq(a: list[float], b: list[float]) -&gt; None:
          from quant.common.floatings import eq
  
          assert isinstance(a, list)
          assert isinstance(b, list)
          assert len(a) == len(b)
          for i in range(len(a)):
  &gt;           assert eq(a[i], b[i])
  E           assert False
  E            +  where False = &lt;function eq at 0x123a84ca0&gt;(8.202096604377518, 8.407775472483964)
  
  quant/test/test_pandas.py:44: AssertionError
  ========================================================================================================================== short test summary info ===========================================================================================================================
  FAILED quant/test/test_pandas.py::TestPandas::test_sma_and_ema - assert False
  ======================================================================================================================== 1 failed, 1 passed in 0.75s =========================================================================================================================
  </code></pre>
  <p>Why after <code>2021-10-11</code>, EMA value between pandas and manually calcuation is different ?</p>
  <h1>Update-1</h1>
  <p>When <code>index=9</code>, we have <code>ALPHA=2/(10+1)=0.1818</code> <code>EMA_df_9=df[&quot;ema10&quot;][index]=7.375896</code>, and <code>PRICE_10=data[&quot;price&quot;][index+1]=11.92</code>, refer to EMA formula, we will have:</p>
  <p><code>EMA_df_10 = ALPHA * PRICE_10 + (1-ALPHA) * EMA_df_9</code></p>
  <p>But in my manually implemented <code>_calculate_ema_impl</code> method, each EMA will calcualte from <strong>index 0</strong>, before values will be ignored.</p>
  <p>So I guess my manually implemented EMA method is buggy.</p>