Вычисление возвратов из фрейма данных с финансовыми данными
У меня есть дата-карта с ежемесячными финансовыми данными:
In [89]: vfiax_monthly.head()
Out[89]:
year month day d open close high low volume aclose
2003-01-31 2003 1 31 731246 64.95 64.95 64.95 64.95 0 64.95
2003-02-28 2003 2 28 731274 63.98 63.98 63.98 63.98 0 63.98
2003-03-31 2003 3 31 731305 64.59 64.59 64.59 64.59 0 64.59
2003-04-30 2003 4 30 731335 69.93 69.93 69.93 69.93 0 69.93
2003-05-30 2003 5 30 731365 73.61 73.61 73.61 73.61 0 73.61
Я пытаюсь вычислить такие возвраты:
In [90]: returns = (vfiax_monthly.open[1:] - vfiax_monthly.open[:-1])/vfiax_monthly.open[1:]
Но я получаю только нули:
In [91]: returns.head()
Out[91]:
2003-01-31 NaN
2003-02-28 0
2003-03-31 0
2003-04-30 0
2003-05-30 0
Freq: BM, Name: open
Я думаю, что потому, что арифметические операции выравниваются по индексу и делают [1:]
и [:-1]
бесполезными.
Мое обходное решение:
In [103]: returns = (vfiax_monthly.open[1:].values - vfiax_monthly.open[:-1].values)/vfiax_monthly.open[1:].values
In [104]: returns = pd.Series(returns, index=vfiax_monthly.index[1:])
In [105]: returns.head()
Out[105]:
2003-02-28 -0.015161
2003-03-31 0.009444
2003-04-30 0.076362
2003-05-30 0.049993
2003-06-30 0.012477
Freq: BM
Есть ли лучший способ расчета прибыли? Мне не нравится преобразование в массив, а затем обратно в серию.
Ответы
Ответ 1
Вместо нарезки используйте .shift
для перемещения позиции индекса значений в DataFrame/Series. Например:
returns = (vfiax_monthly.open - vfiax_monthly.open.shift(1))/vfiax_monthly.open.shift(1)
Это то, что pct_change
делает под капотом. Вы также можете использовать его для других функций, например:
(3*vfiax_monthly.open + 2*vfiax_monthly.open.shift(1))/5
Возможно, вы также захотите изучить скользящие и оконные функции для других видов анализа финансовых данных.
Ответ 2
Самый простой способ сделать это - использовать метод DataFrame.pct_change().
Вот краткий пример
In[1]: aapl = get_data_yahoo('aapl', start='11/1/2012', end='11/13/2012')
In[2]: appl
Out[2]:
Open High Low Close Volume Adj Close
Date
2012-11-01 598.22 603.00 594.17 596.54 12903500 593.83
2012-11-02 595.89 596.95 574.75 576.80 21406200 574.18
2012-11-05 583.52 587.77 577.60 584.62 18897700 581.96
2012-11-06 590.23 590.74 580.09 582.85 13389900 580.20
2012-11-07 573.84 574.54 555.75 558.00 28344600 558.00
2012-11-08 560.63 562.23 535.29 537.75 37719500 537.75
2012-11-09 540.42 554.88 533.72 547.06 33211200 547.06
2012-11-12 554.15 554.50 538.65 542.83 18421500 542.83
2012-11-13 538.91 550.48 536.36 542.90 19033900 542.90
In[3]: aapl.pct_change()
Out[3]:
Open High Low Close Volume Adj Close
Date
2012-11-01 NaN NaN NaN NaN NaN NaN
2012-11-02 -0.003895 -0.010033 -0.032684 -0.033091 0.658945 -0.033090
2012-11-05 -0.020759 -0.015378 0.004959 0.013558 -0.117186 0.013550
2012-11-06 0.011499 0.005053 0.004311 -0.003028 -0.291453 -0.003024
2012-11-07 -0.027769 -0.027423 -0.041959 -0.042635 1.116864 -0.038263
2012-11-08 -0.023020 -0.021426 -0.036815 -0.036290 0.330747 -0.036290
2012-11-09 -0.036049 -0.013073 -0.002933 0.017313 -0.119522 0.017313
2012-11-12 0.025406 -0.000685 0.009237 -0.007732 -0.445323 -0.007732
2012-11-13 -0.027502 -0.007250 -0.004251 0.000129 0.033244 0.000129
Ответ 3
Лучший способ вычислить pd.DataFrame.pct_change()
доходы без какой-либо вероятности смещения - использовать встроенную функцию pd.DataFrame.pct_change()
. В вашем случае все, что вам нужно использовать, это эта функция, так как у вас есть ежемесячные данные, и вы ищете ежемесячный доход.
Например, если вы хотите посмотреть на возврат за 6 месяцев, вы просто установите параметр df.pct_change(periods = 6)
и это даст вам возврат за 6 месяцев.
Поскольку у вас сравнительно небольшой набор данных, самый простой способ - это pct_change()
параметров, по которым необходимо рассчитать данные, а затем снова использовать pct_change()
.
Однако из-за хороших свойств log
обычно используется формула для расчета доходности (если вы планируете делать статистику по возвращаемому ряду):
![enter image description here]()
Что бы вы реализовали так:
log_return = np.log(vfiax_monthly.open/vfiax_monthly.open.shift())
Ответ 4
Можно также использовать сочетание методов diff
и shift
для серии панд:
retrun = vfiax_monthly.open.diff()/vfiax_monthly.open.shift(1)