Избегайте зацикливания для вычисления простых сигналов пересечения скользящих средних - PullRequest
0 голосов
/ 11 мая 2018

Я хотел бы рассчитать сигналы покупки и продажи акций на основе пересечения простой скользящей средней (SMA).Сигнал на покупку должен быть подан, как только SMA_short выше, чем SMA_long (т. Е. SMA_difference > 0).Чтобы избежать слишком быстрой продажи позиции, я хотел бы получить сигнал на продажу только после того, как SMA_shor t значительно выйдет за пределы креста (т. Е. SMA_difference <-1) и, что немаловажно, даже если это будет длиться дольше одного дня.</p>

Мне удалось с помощью этой помочь реализовать ее (см. Ниже):

  • Сигналы покупки и продажи обозначены в и из .
  • Столбец Позиция учитывает сначала buy_limit .
  • В Position_extended и в - этозатем установите для всех случаев, когда SMA_short только что пересекли SMA_long ( SMA_short <<em> SMA_long ), но SMA_short > -1.Для этого учитывается расширенная позиция i-1 в случае, если пересечение было более одного дня назад, но SMA_short осталось: 0 > SMA_short > -1.

Python code

import pandas as pd
import numpy as np

index = pd.date_range('20180101', periods=6)
df = pd.DataFrame(index=index)
df["SMA_short"] = [9,10,11,10,10,9]
df["SMA_long"] = 10
df["SMA_difference"] = df["SMA_short"] - df["SMA_long"]
buy_limit = 0
sell_limit = -1

df["Position"] = np.where((df["SMA_difference"] > buy_limit),"in","out")
df["Position_extended"] = df["Position"]
for i in range(1,len(df)):
    df.loc[index[i],"Position_extended"] =  \
    np.where((df.loc[index[i], "SMA_difference"] > sell_limit) \
              & (df.loc[index[i-1],"Position_extended"] == "in") \
              ,"in",df.loc[index[i],'Position'])
print df 

Результат:

              SMA_short  SMA_long  SMA_difference Position Position_extended
2018-01-01          9        10              -1      out               out
2018-01-02         10        10               0      out               out
2018-01-03         11        10               1       in                in
2018-01-04         10        10               0      out                in
2018-01-05         10        10               0      out                in
2018-01-06          9        10              -1      out               out

Код работает, однако он использует цикл for, который значительно замедляет работу сценария истановится неприменимым в более широком контексте этого анализа.Поскольку SMA пересечение является таким широко используемым инструментом, мне было интересно, сможет ли кто-нибудь найти более элегантное и быстрое решение для этого.

Ответы [ 2 ]

0 голосов
/ 16 мая 2018

По сути, вы пытаетесь избавиться от двойных нулевых записей, распространяя последнее ненулевое значение.Аналогично удержанию нулевого порядка.Вы можете сделать это, сначала заменив нулевые значения значениями NaN, а затем интерполировав их по последним значениям, используя ffill.

import pandas as pd
import numpy as np

index = pd.date_range('20180101', periods=6)
df = pd.DataFrame(index=index)
df["SMA_short"] = [9,10,11,10,10,9]
df["SMA_long"] = 10
df["SMA_difference"] = df["SMA_short"] - df["SMA_long"]
buy_limit = 0
sell_limit = -1

df["ZOH"] = df["SMA_difference"].replace(0,np.nan).ffill()
df["Position"] = np.where((df["ZOH"] > buy_limit),"in","out")
print df 

, чтобы получить:

            SMA_short  SMA_long  SMA_difference  ZOH Position
2018-01-01          9        10              -1 -1.0      out
2018-01-02         10        10               0 -1.0      out
2018-01-03         11        10               1  1.0       in
2018-01-04         10        10               0  1.0       in
2018-01-05         10        10               0  1.0       in
2018-01-06          9        10              -1 -1.0      out
0 голосов
/ 11 мая 2018

Если для строки T в качестве входных данных требуется значение, вычисленное в строке T-1, то вам, вероятно, потребуется выполнить итеративный расчет. Как правило, тестирование на истории выполняется путем последовательного просмотра ценовых данных. Вы можете рассчитать некоторые сигналы только на основании состояния рынка, но вы не будете знать стоимость портфеля, pnl или позиции портфеля, если не начнете с самого начала и не продвинетесь во времени. Вот почему, если вы посмотрите на сайт, похожий на Quantopian, тестирование всегда начинается с даты начала до конца.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...