#python #pandas #quantitative-finance #momentum
#python #pandas #количественный-финансы #momentum
Вопрос:
Я пытаюсь построить стратегию портфеля, следующую за трендом, на основе индекса S amp; P500 (данные за месяц)
Я использовал коэффициент фрактальной эффективности Кауфмана для фильтрации сигнала whipsaw (http://etfhq.com/blog/2011/02/07/kaufmans-efficiency-ratio /)
Я преуспел в кодировании, но это очень неуклюже, поэтому мне нужен совет по улучшению кода.
СТРАТЕГИИ
- Получить данные индекса S amp; P 500 от yahoo finance
- Вычислите коэффициент эффективности Кауфмана для периода ретроспективного анализа X (1, если close> close (n), 0)
- Среднее расчетное значение 2, период времени от 1 до 12 —> Ежемесячный коэффициент распределения активов, 1-коэффициент распределения активов = денежные средства (3% в год)
У меня возникают трудности с усреднением коэффициента эффективности от 1 до 12. Конечно, я знаю, что это может быть просто реализовано с помощью цикла for, и это очень простая задача, но я потерпел неудачу.
Мне нужен более краткий и уточненный код, кто-нибудь может мне помочь?
a['meanfractal']
меня беспокоит приведенный ниже код..
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import pandas_datareader.data as web
def price(stock, start):
price = web.DataReader(name=stock, data_source='yahoo', start=start)['Adj Close']
return price.div(price.iat[0]).resample('M').last().to_frame('price')
a = price('SPY','2000-01-01')
def fractal(a,p):
a['direction'] = np.where(a['price'].diff(p)>0,1,0)
a['abs'] = a['price'].diff(p).abs()
a['volatility'] = a.price.diff().abs().rolling(p).sum()
a['fractal'] = a['abs'].values/a['volatility'].values*a['direction'].values
return a['fractal']
def meanfractal(a):
a['meanfractal']= (fractal(a,1).values fractal(a,2).values fractal(a,3).values fractal(a,4).values fractal(a,5).values fractal(a,6).values fractal(a,7).values fractal(a,8).values fractal(a,9).values fractal(a,10).values fractal(a,11).values fractal(a,12).values)/12
a['portfolio1'] = (a.price/a.price.shift(1).values*a.meanfractal.shift(1).values (1-a.meanfractal.shift(1).values)*1.03**(1/12)).cumprod()
a['portfolio2'] = ((a.price/a.price.shift(1).values*a.meanfractal.shift(1).values 1.03**(1/12))/(1 a.meanfractal.shift(1))).cumprod()
a=a.dropna()
a=a.div(a.ix[0])
return a[['price','portfolio1','portfolio2']].plot()
print(a)
plt.show()
Ответ №1:
Вы могли бы еще больше упростить, сохранив значения, соответствующие p
в DF
, а не вычисляя для каждой серии отдельно, как показано:
def fractal(a, p):
df = pd.DataFrame()
for count in range(1,p 1):
a['direction'] = np.where(a['price'].diff(count)>0,1,0)
a['abs'] = a['price'].diff(count).abs()
a['volatility'] = a.price.diff().abs().rolling(count).sum()
a['fractal'] = a['abs']/a['volatility']*a['direction']
df = pd.concat([df, a['fractal']], axis=1)
return df
Затем вы можете назначить повторяющиеся операции переменной, что сокращает время повторного вычисления.
def meanfractal(a, l=12):
a['meanfractal']= pd.DataFrame(fractal(a, l)).sum(1,skipna=False)/l
mean_shift = a['meanfractal'].shift(1)
price_shift = a['price'].shift(1)
factor = 1.03**(1/l)
a['portfolio1'] = (a['price']/price_shift*mean_shift (1-mean_shift)*factor).cumprod()
a['portfolio2'] = ((a['price']/price_shift*mean_shift factor)/(1 mean_shift)).cumprod()
a.dropna(inplace=True)
a = a.div(a.ix[0])
return a[['price','portfolio1','portfolio2']].plot()
Полученный график:
meanfractal(a)
Примечание: если скорость не является серьезной проблемой, вы можете выполнять операции с помощью встроенных методов, присутствующих в pandas
, вместо преобразования их в соответствующие numpy
значения массива.
Комментарии:
1. Большое вам спасибо… Это было очень полезно
2. Когда я вычисляю поэлементную операцию между фреймами данных, иногда возникает ошибка, если я не кодирую с помощью ‘df.values’, но, похоже, в вашем коде нет проблем, напрямую работающих между фреймами данных (например, a [‘fractal’] = a [‘abs’] / a[‘volatility’] * a[‘направление’] ). В чем разница?
3. Хороший вопрос. Пока они являются частью одного и того же фрейма данных, вы можете выполнять арифметические операции, транслируя их. Проблема возникает, когда вы хотите поэлементно умножить два фрейма данных или две их серии, имеющие несоответствие в размерах, что приводит к вашему
DF
возвратуNans
. В этих случаях вы должны преобразовать его в егоnumpy
аналог, обратившись к.values
атрибутуDF's
объекта, с которым нужно работать.4. @ Nickil Maveli
5. Спасибо за любезное объяснение, теперь я ясно понял, чего я и ожидал.