Ячейка кадра данных должна быть заблокирована и использована для расчета текущего баланса (следующий вопрос) - PullRequest
1 голос
/ 19 марта 2020

(Это дополнительный вопрос к моему предыдущему вопросу , на который был дан правильный ответ).

Скажите, у меня есть следующий фрейм данных

import pandas as pd
df = pd.DataFrame()

df['E'] = ('SIT','SCLOSE', 'SHODL', 'SHODL', 'SHODL', 'SHODL', 'SHODL', 'SHODL','SHODL','SCLOSE_BUY','BCLOSE_SELL', 'BHODL', 'BHODL', 'BHODL', 'BHODL', 'BHODL', 'BHODL','BUY','SIT','SIT')

df['F'] = (0.00,1.00,10.00, 5.00,6.00,-6.00, 6.00, 2.00,10.00,10.00,-8.00,33.00,-15.00,6.00,-1.00,5.00,10.00,0.00,0.00,0.00)

df.loc[19, 'G'] = 100.0000

С колонкой G начиная с 100, применяются те же правила, что и для моего предыдущего вопроса, согласно которому при совершении покупки или продажи по столбцу E соответствующий остаток в столбце G блокируется и непрерывно используется в качестве базовой суммы для расчета текущего баланса, причем столбец F представляет собой% увеличения / уменьшения для каждой строки в текущем балансе, пока не появится BCLOSE или SCLOSE на col E.

Я объяснил правила в предыдущем вопросе, однако новым для этого вопроса является то, что если SCLOSE_BUY показан, то ПРОДАЖА закрыта, а ПОКУПКА открыта, и наоборот для BCLOSE_SELL. Строка BCLOSE, SCLOSE, SCLOSE_BUY или BCLOSE_SELL станет последней строкой для расчета текущего баланса и будет использоваться в качестве базы, когда на следующих покупках будет показана покупка или продажа

Для вашего успешного ответа на мой предыдущий вопрос был сделанный Энди Л. следующим образом, однако этот ответ не может обработать новый сценарий, когда BCLOSE_SELL и SCLOSE_BUY происходят один за другим

df1 = df[::-1]
s = df1.B.isin(['BCLOSE','SCLOSE']).shift(fill_value=False).cumsum()
grps = df1.groupby(s)
init_val= 100
l = []
for _, grp in grps:
    s = grp.C * 0.01 * init_val
    s.iloc[0] = init_val
    s = s.cumsum()
    init_val = s.iloc[-1]
    l.append(s)

Приведенный выше ответ не решает проблему, с которой я сталкиваюсь в реальной жизни, в результате чего вместо При получении BCLOSE вместо этого я получаю BCLOSE_SELL, который в основном превращает ПОКУПКУ в ПРОДАЖУ (ie. Я закрываю ПОКУПКУ и открываю ПРОДАЖУ), которая становится базовой суммой для текущих строк.

Если строки продолжаются как SHODL, я могу настроить код так, чтобы текущий баланс был правильно рассчитан, однако, если я впоследствии получу SCLOSE_BUY (как видно в строке 9 моего фрейма данных), мне нужно заставить эту строку закрыть SELL и снова открыть BUY и эту строку также будет новая базовая сумма для моего бега баланс.

Я понимаю, что все это звучит странно, так как приведенный ниже столбец, добавленный к моему приведенному выше кадру данных, должен выглядеть как результат.

df['G'] = (191.62,191.62,190.19,175.89,168.74,160.16,168.74,160.16,157.3,143,130,138,105,120,114,115,110,100,100,100)

Ответы [ 2 ]

1 голос
/ 19 марта 2020

Вам просто нужно изменить мое решение на 2 места. Добавьте 'BCLOSE_SELL', 'SCLOSE_BUY' к isin проверке и измените присвоение init_val

df1 = df[::-1]
s = (df1.E.isin(['BCLOSE', 'SCLOSE', 'BCLOSE_SELL', 'SCLOSE_BUY'])
          .shift(fill_value=False).cumsum())  ###add 'BCLOSE_SELL', 'SCLOSE_BUY'
grps = df1.groupby(s)
init_val= 100
l = []
for _, grp in grps:
    s = grp.F * 0.01 * init_val
    s.iloc[0] += init_val    ###change here. Use `+=` instead of `=`
    s = s.cumsum()
    init_val = s.iloc[-1]
    l.append(s)

df['G'] = pd.concat(l)

Out[96]:
              E     F       G
0           SIT   0.0  191.62
1        SCLOSE   1.0  191.62
2         SHODL  10.0  190.19
3         SHODL   5.0  175.89
4         SHODL   6.0  168.74
5         SHODL  -6.0  160.16
6         SHODL   6.0  168.74
7         SHODL   2.0  160.16
8         SHODL  10.0  157.30
9    SCLOSE_BUY  10.0  143.00
10  BCLOSE_SELL  -8.0  130.00
11        BHODL  33.0  138.00
12        BHODL -15.0  105.00
13        BHODL   6.0  120.00
14        BHODL  -1.0  114.00
15        BHODL   5.0  115.00
16        BHODL  10.0  110.00
17          BUY   0.0  100.00
18          SIT   0.0  100.00
19          SIT   0.0  100.00
1 голос
/ 19 марта 2020

У меня есть хорошо документированный ответ на похожий вопрос, опубликованный здесь , однако позвольте мне немного его настроить, чтобы он мог быть применим к только что заданному вопросу. По сути, все, что вам нужно сделать, это добавить две новые точки останова в BCLOSE_SELL и SCLOSE_BUY следующим образом:

df.index[df[type_col].isin(['BCLOSE', 'SCLOSE', 'BCLOSE_SELL', 'SCLOSE_BUY'])][::-1]

В приведенной выше строке type_col - это имя столбца, который определяет действие (например, SHOLD или BCLOSE) или, в вашем случае, столбец E.

. Вы можете найти полный и обновленный фрагмент кода, который работает с обоими вашими вопросами ниже:

# basic setup
type_col = 'E'  # the name of the action type column
change_col = 'F'  # the name of the delta change column
res_col = 'G'  # the name of the resulting column
value = 100  # you can specify any initial value here
PERCENTAGE_CONST = 100

endpoints = [df.first_valid_index(), df.last_valid_index()]
# occurrences of 'BCLOSE', 'SCLOSE', 'BCLOSE_SELL' and 'SCLOSE_BUY' that break the sequence
breakpoints = df.index[df[type_col].isin(['BCLOSE','SCLOSE', 'BCLOSE_SELL', 'SCLOSE_BUY'])][::-1]
# removes the endpoints of the dataframe that do not break the structure
breakpoints = breakpoints.drop(endpoints, errors='ignore')

for i in range(len(breakpoints) + 1):

    prv = breakpoints[i - 1] - 1 if i else -1  # previous or first breakpoint
    try:
        nex = breakpoints[i] - 1  # next breakpoint
    except IndexError:
        nex = None  # last breakpoint

    # cumulative sum of values adjusted for the percentage change appended to the resulting column
    res = value + (df[change_col][prv: nex: -1] * value / PERCENTAGE_CONST).cumsum()[::-1]
    df.loc[res.index, res_col] = res

    # saving the value that will be the basis for percentage calculations
    # for the next breakpoint
    value = res.iloc[0]

Полученный результат соответствует ожидаемому результату:

>>> df
              E     F       G
0           SIT   0.0  191.62
1        SCLOSE   1.0  191.62
2         SHODL  10.0  190.19
3         SHODL   5.0  175.89
4         SHODL   6.0  168.74
5         SHODL  -6.0  160.16
6         SHODL   6.0  168.74
7         SHODL   2.0  160.16
8         SHODL  10.0  157.30
9    SCLOSE_BUY  10.0  143.00
10  BCLOSE_SELL  -8.0  130.00
11        BHODL  33.0  138.00
12        BHODL -15.0  105.00
13        BHODL   6.0  120.00
14        BHODL  -1.0  114.00
15        BHODL   5.0  115.00
16        BHODL  10.0  110.00
17          BUY   0.0  100.00
18          SIT   0.0  100.00
19          SIT   0.0  100.00
...