Это моя последняя попытка после публикации нескольких вопросов, которые могли быть плохо рассмотрены / описаны. Я хочу получить этот DataFrame как результат:

        Signal   price  buy_units   sell_units   cashflow  balance
   Index
      0     0       40          0         0           0     100000
      1     1       50       2000         0      -100000         0
      2    -1      100          0     -2000      +200000    200000  
      3     1       50       4000         0      -200000         0
      4    -1       70          0     -4000      +280000    280000

Это бэктест стратегии биржевой торговли. Когда Signal равно == 1, buy_units равно текущему balance (значение из предыдущей строки), разделенному на price. Затем balance уменьшается на cashflow (то есть единицы x цена * -1). Остальное не требует пояснений. Проблема: вычисление buy_units без итерации, но в векторизованном виде. У кого есть идеи как это решить?

В конечном итоге я хотел бы спроектировать это в классе с методами «Расчет единиц» и «Расчет баланса», но на первом этапе это не обязательно.

3
Al_Iskander 6 Июн 2016 в 12:25
1
Похоже, вам нужно динамически заполнять столбец баланса (buy units зависит от balance, balance зависит от cashflow и cashflow зависит от buy units верно?) И я определенно не эксперт, но это похоже на работу, требующую циклов.
 – 
ayhan
6 Июн 2016 в 12:40
@ayhan, скорее всего, это причина, по которой я до сих пор не мог разобраться. Странно, что ответ, касающийся shift (), исчез, я хотел еще раз взглянуть на него, но то, что вы утверждаете, подтверждает мое мнение. Что заставляет меня задуматься, так это то, что проблема легко решается в Excel без какого-либо скрипта, но становится более сложной в pandas.
 – 
Al_Iskander
6 Июн 2016 в 12:58
Возможно, они удалили его, чтобы посмотреть или отредактировать его еще раз. Я согласен с тем, что некоторые операции в Excel очень естественны, и вы можете выполнять их очень легко, но когда вы пытаетесь сделать то же самое в пандах, это становится сложным. Вероятно, потому, что сама операция итеративна.
 – 
ayhan
6 Июн 2016 в 13:11
@Al_Iskander, я удалил свой ответ, потому что он мне показался неправильным. Пожалуйста, найдите мой обновленный ответ.
 – 
IanS
6 Июн 2016 в 18:16

2 ответа

Если сигналы -1 и +1 всегда чередуются, как в примере, то баланс на шаге n+2 равен остатку на шаге n, умноженному на возврат цены между n+1 и n+2.

Я использую накопленный продукт, чтобы преобразовать это в векторизованные операции в пандах:

# initialize balance
df['balance'] = 0.0
df.balance.iloc[0] = 10000.0

# calculate returns
df['return'] = df.price / df.price.shift()

# calculate balance where signal is -1
df.loc[df.Signal == -1, 'balance'] = \
    df.balance.iloc[0] * df.loc[df.Signal == -1, 'return'].cumprod()

Денежные потоки и количество единиц могут быть легко рассчитаны по балансу.

1
IanS 6 Июн 2016 в 18:12
Я имел это в виду, но, вероятно, использовал неправильно. То, что я сделал, было df.balance.shift (1), чтобы обратиться к предыдущей строке ... ваше решение, похоже, в правильном направлении
 – 
Al_Iskander
6 Июн 2016 в 12:40
Огромное спасибо. Сигналы не обязательно чередуются напрямую. Между ними может быть 0.
 – 
Al_Iskander
6 Июн 2016 в 18:32
Предложение не работает для моей цели. Также сдвиг () не работал. Я думаю, что нет векторизованного решения, как сказал ранее @ayhan.
 – 
Al_Iskander
6 Июн 2016 в 20:17
Что значит не работала смена? Какую версию панд (pandas.__version__) вы используете?
 – 
IanS
7 Июн 2016 в 10:39
2
Нам потребуются точные правила того, что происходит, когда 0 следует за 1 или -1. Но это правда, если мы не найдем способ математически упростить задачу, тогда, вероятно, не будет векторизованного решения.
 – 
IanS
7 Июн 2016 в 10:40

Вы можете создать временный фрейм данных для выполнения ваших вычислений:

temp = df[df.balance == 1]

Затем выполните вычисления на этом фрейме данных:

df.ix[df.balance == 1,'buy_units'] = temp.balance/temp.price

И удалите временный фрейм данных:

%reset selective -f temp
0
ysearka 6 Июн 2016 в 14:46