14 марта 2016 QuantAlgos
Небольшая статья с ресурса http://www.talaikis.com/ о построении простой стратегии, использующую наивный байесовский классификатор при создании процесса возврата к среднему. Весь код в статье приведен на языке Python.
Это достаточно большая область исследований, но расскажем все очень кратко. Мы попытаемся найти взаимоотношение между временными сериями (в данном случае возьмем в качестве сигнала взаимный фонд XLF из финансового сектора, сдвинутый по времени на 1 день назад), а нашей целью будет фьючерс SnP500 в форме CFD. Будем входить в длинную позицию по этой бумаге при нулевой вероятности приращения. Логически нулевая вероятность ни о чем не говорит, другими словами, будем покупать возврат к среднему.
1. Получение данных
2. Далее мы конструируем матрицу ошибок.Если сигнал растет и SnP500 растет - это истинное положительное значение, если сигнал вверх, а SnP500 -вниз, это ложное положительное значение, то же для отрицательных сигналов. Мы делаем это двумя способами:
3. Преобразуем сигналы в булевы переменные, используя скользящую сумму из 10 значений по всем сигналам:
4. Теперь попытаемся определить вероятность сигналов обоих направлений. Для этого используем простую формулу частот:
смысл которой в том, что вероятность события равна числу желаемых событий , деленных на число всех возможных событий:
5. Вычислим вероятности противоположных событий:
6. Сейчас мы можем вычислить сигналы и прибыльность. Будем использовать десятикратное плечо при расчете прибыли. Код ниже дан для ситуации " вход в лонг при отрицательной вероятности":
В заглавии статьи показан график кумулятивной прибыли по сравнению со стратегией "купил и держи" ( линия зеленого цвета).
Ниже - график просадок:
Конечно, векторизованный бэктест показывает только, как это было бы при входе и выходе на закрытии дня, не учитывает комиссий и т.п.
Это достаточно большая область исследований, но расскажем все очень кратко. Мы попытаемся найти взаимоотношение между временными сериями (в данном случае возьмем в качестве сигнала взаимный фонд XLF из финансового сектора, сдвинутый по времени на 1 день назад), а нашей целью будет фьючерс SnP500 в форме CFD. Будем входить в длинную позицию по этой бумаге при нулевой вероятности приращения. Логически нулевая вероятность ни о чем не говорит, другими словами, будем покупать возврат к среднему.
1. Получение данных
Y = read_mongo(dbase, "S&P5001440")
X = read_mongo(dbase, syms[s]).shift()
#готовим набор данных
res = pd.concat([X.CLOSE, Y.CLOSE], axis=1, join_axes=[X.index]).pct_change().dropna()
res.columns = ['X', 'Y']
2. Далее мы конструируем матрицу ошибок.Если сигнал растет и SnP500 растет - это истинное положительное значение, если сигнал вверх, а SnP500 -вниз, это ложное положительное значение, то же для отрицательных сигналов. Мы делаем это двумя способами:
#матрица ошибок
res['true_positive'] = np.where(np.where((res['X'] > 0), res['Y'], 0) > 0, res['Y'], 0)
res['false_positive'] = np.where((np.where((res['X'] > 0), res['Y'], 0) < 0), res['Y'], 0)
res['true_negative'] = np.where((res['X'] < 0) & (res['Y'] < 0), res['Y'], 0)
res['false_negative'] = np.where((res['X'] < 0) & (res['Y'] > 0), res['Y'], 0)
3. Преобразуем сигналы в булевы переменные, используя скользящую сумму из 10 значений по всем сигналам:
#скользящая сумма сигналов
w = 10
res['true_positive_sum'] = pd.rolling_sum(res['true_positive'].astype(bool), window=w)
res['false_positive_sum'] = pd.rolling_sum(res['false_positive'].astype(bool), window=w)
res['true_negative_sum'] = pd.rolling_sum(res['true_negative'].astype(bool), window=w)
res['false_negative_sum'] = pd.rolling_sum(res['false_negative'].astype(bool), window=w)
4. Теперь попытаемся определить вероятность сигналов обоих направлений. Для этого используем простую формулу частот:
смысл которой в том, что вероятность события равна числу желаемых событий , деленных на число всех возможных событий:
res['accuracy'] = (res['true_positive_sum'] + res['true_negative_sum']) / (res['true_positive_sum'] + \
res['true_negative_sum'] + res['false_positive_sum'] + res['false_negative_sum'])
plt.plot(res['accuracy'])
plt.axhline(0.5, color = 'r', xmax=5)
plt.show()
5. Вычислим вероятности противоположных событий:
res['true_positive_ratio'] = res['true_positive_sum'] /(res['true_positive_sum'] + res['false_negative_sum'])
res['false_positive_ratio'] = res['false_positive_sum'] / (res['false_positive_sum'] + res['true_negative_sum'])
res['true_negative_ratio'] = 1 - res['true_positive_ratio']
res['false_negative_ratio'] = 1 - res['false_positive_ratio']
6. Сейчас мы можем вычислить сигналы и прибыльность. Будем использовать десятикратное плечо при расчете прибыли. Код ниже дан для ситуации " вход в лонг при отрицательной вероятности":
res['signal'] = np.where(res['true_negative_ratio'] >= 1, 1, 0)
res['returns'] = res['signal'].shift() * res['Y'] * 10.0
В заглавии статьи показан график кумулятивной прибыли по сравнению со стратегией "купил и держи" ( линия зеленого цвета).
Ниже - график просадок:
Конечно, векторизованный бэктест показывает только, как это было бы при входе и выходе на закрытии дня, не учитывает комиссий и т.п.
Не является индивидуальной инвестиционной рекомендацией | При копировании ссылка обязательна | Нашли ошибку - выделить и нажать Ctrl+Enter | Жалоба