Python — флаг открытой позиции портфеля

#python #pandas

#питон #pandas

Вопрос:

У меня есть фрейм данных ниже:

  ticker       date  buy_fg  sell_fg
50      ABC 2010-01-01     0.0      2.0
51      ABC 2010-01-08     0.0      2.0
52      ABC 2010-01-15     0.0      2.0
53      ABC 2010-01-22     0.0      2.0
1512    ABC 2010-01-29     1.0      0.0
54      ABC 2010-02-05     0.0      2.0
55      ABC 2010-02-12     0.0      2.0
56      ABC 2010-02-19     0.0      2.0
57      ABC 2010-02-26     0.0      2.0
58      ABC 2010-03-05     0.0      2.0
59      ABC 2010-03-12     0.0      2.0
60      ABC 2010-03-19     0.0      2.0
61      ABC 2010-03-26     0.0      2.0
1417    ABC 2010-04-02     1.0      0.0
1409    ABC 2010-04-09     1.0      0.0
62      ABC 2010-04-23     0.0      2.0
63      ABC 2010-05-07     0.0      2.0
64      ABC 2010-05-14     0.0      2.0
65      ABC 2010-05-21     0.0      2.0
66      ABC 2010-05-28     0.0      2.0
 

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

 # Initiate the global, default buy flag
hold_flag =  False
 
# Custom function to flick the global flag based on `buy_fg` column
def hold(value):
    global hold_flag 
    if value == 1:
        if hold_flag is False:
            hold_flag = True
            return '3'
        if hold_flag is True:
            hold_flag = False
            return '1'
    else:
        return '0'

new_report['hold_fg'] = new_report['buy_fg'].apply(hold)
 

Это создало hold_fg столбец. Но теперь мне нужно расширить это, чтобы рассмотреть все три *_fg столбца, чтобы обеспечить окончательное действие.

       ticker       date  buy_fg  sell_fg  action hold_fg
50      ABC 2010-01-01     0.0      2.0       0       0
51      ABC 2010-01-08     0.0      2.0       0       0
52      ABC 2010-01-15     0.0      2.0       0       0
53      ABC 2010-01-22     0.0      2.0       0       0
1512    ABC 2010-01-29     1.0      0.0       0       1
54      ABC 2010-02-05     0.0      2.0       0       0
55      ABC 2010-02-12     0.0      2.0       0       0
56      ABC 2010-02-19     0.0      2.0       0       0
57      ABC 2010-02-26     0.0      2.0       0       0
58      ABC 2010-03-05     0.0      2.0       0       0
59      ABC 2010-03-12     0.0      2.0       0       0
60      ABC 2010-03-19     0.0      2.0       0       0
61      ABC 2010-03-26     0.0      2.0       0       0
1417    ABC 2010-04-02     1.0      0.0       0       1
1409    ABC 2010-04-09     1.0      0.0       0       3
62      ABC 2010-04-23     0.0      2.0       0       0
63      ABC 2010-05-07     0.0      2.0       0       0
64      ABC 2010-05-14     0.0      2.0       0       0
65      ABC 2010-05-21     0.0      2.0       0       0
66      ABC 2010-05-28     0.0      2.0       0       0
 

Я пробовал следующее, но это не работает:

 new_report['action'] = 0

buy_flag = False

def action(value):
    global buy_flag
    if new_report['hold_fg'] == 1:
        buy_flag = True
        return 'BUY'
    if new_report['hold_fg'] == 3:
        buy_flag = True
        return 'HOLD'
    if new_report['sell_fg'] == 2:
        buy_flag = False
        return 'SELL'
    else:
        return '0'
 

Есть идеи о том, как я могу это решить?

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

      ticker       date  buy_fg  sell_fg action hold_fg
50      ABC 2010-01-01     0.0      2.0    NIL       0
51      ABC 2010-01-08     0.0      2.0    NIL       0
52      ABC 2010-01-15     0.0      2.0    NIL       0
53      ABC 2010-01-22     0.0      2.0    NIL       0
1512    ABC 2010-01-29     1.0      0.0    BUY       1
54      ABC 2010-02-05     0.0      2.0   SELL       0
55      ABC 2010-02-12     0.0      2.0    NIL       0
56      ABC 2010-02-19     0.0      2.0    NIL       0
57      ABC 2010-02-26     0.0      2.0    NIL       0
58      ABC 2010-03-05     0.0      2.0    NIL       0
59      ABC 2010-03-12     0.0      2.0    NIL       0
60      ABC 2010-03-19     0.0      2.0    NIL       0
61      ABC 2010-03-26     0.0      2.0    NIL       0
1417    ABC 2010-04-02     1.0      0.0    BUY       1
1409    ABC 2010-04-09     1.0      0.0    HOLD      3
62      ABC 2010-04-23     0.0      2.0    SELL      0
63      ABC 2010-05-07     0.0      2.0    NIL       0
64      ABC 2010-05-14     0.0      2.0    NIL       0
65      ABC 2010-05-21     0.0      2.0    NIL       0
66      ABC 2010-05-28     0.0      2.0    NIL       0
 

Комментарии:

1. судя по вашей action колонке, вы на правильном пути, но я не могу понять ваш вопрос: чего именно вам сейчас не хватает?

2. Это немного сбивает с толку. Не могли бы вы подробнее остановиться на этом it needs to show a 'SELL' only when a 'BUY has been registered' ? Какой ожидаемый результат вы ищете?

3. Обновлено с учетом логики и ожидаемого результата.

4. Поскольку вы обновили / изменили вопрос, можете ли вы также снова обновить ожидаемый результат?

5. Обновлено — единственное отличие от вашего обновленного решения — индексы 1417, 1409 и 62

Ответ №1:

Я думаю, вам нужно будет отслеживать статус и применять требуемую логику на основе этого. Вот пример использования пользовательской функции для этого. Надеюсь, это поможет!

  # Initiate the global, default buy flag
 >>> buy_flag =  False
 
 # Custom function to flick the global flag based on `buy_fg` column
 >>> def sell_or_buy(value):
    global buy_flag 
    if value == 1:
        if buy_flag is False:
            buy_flag = True
            return 'BUY'
        if buy_flag is True:
            return 'HOLD'
    if value == 0:
        if buy_flag == 1:
            buy_flag = False
            return 'SELL'
        if buy_flag == 0:
            return 'NIL'

>>> df['action'] = df['buy_fg'].apply(sell_or_buy)

>>> df
    ticker            date  buy_fg  sell_fg action
0       50  ABC 2010-01-01     0.0      2.0    NIL
1       51  ABC 2010-01-08     0.0      2.0    NIL
2       52  ABC 2010-01-15     0.0      2.0    NIL
3       53  ABC 2010-01-22     0.0      2.0    NIL
4     1512  ABC 2010-01-29     1.0      0.0    BUY
5       54  ABC 2010-02-05     0.0      2.0   SELL
6       55  ABC 2010-02-12     0.0      2.0    NIL
7       56  ABC 2010-02-19     0.0      2.0    NIL
8       57  ABC 2010-02-26     0.0      2.0    NIL
9       58  ABC 2010-03-05     0.0      2.0    NIL
10      59  ABC 2010-03-12     0.0      2.0    NIL
11      60  ABC 2010-03-19     0.0      2.0    NIL
12      61  ABC 2010-03-26     0.0      2.0    NIL
13    1417  ABC 2010-04-02     1.0      0.0    BUY
14    1409  ABC 2010-04-09     1.0      0.0   HOLD
15      62  ABC 2010-04-23     0.0      2.0   SELL
16      63  ABC 2010-05-07     0.0      2.0    NIL
17      64  ABC 2010-05-14     0.0      2.0    NIL
18      65  ABC 2010-05-21     0.0      2.0    NIL
19      66  ABC 2010-05-28     0.0      2.0    NIL
 

Редактировать:
Это сделано для удовлетворения ваших последних требований. Поскольку из-за того, как вы обновили вопрос, он становится немного запутанным, я просто изменю свой ответ, чтобы добавить его к приведенному выше фрейму данных.

 >>> d={'NIL': 0, 'BUY': 1, 'SELL': 2, 'HOLD' : 3}
>>> df['hold_fg'] = df.action.map(d)
>>> df
    ticker            date  buy_fg  sell_fg action  hold_fg
0       50  ABC 2010-01-01     0.0      2.0    NIL        0
1       51  ABC 2010-01-08     0.0      2.0    NIL        0
2       52  ABC 2010-01-15     0.0      2.0    NIL        0
3       53  ABC 2010-01-22     0.0      2.0    NIL        0
4     1512  ABC 2010-01-29     1.0      0.0    BUY        1
5       54  ABC 2010-02-05     0.0      2.0   SELL        2
6       55  ABC 2010-02-12     0.0      2.0    NIL        0
7       56  ABC 2010-02-19     0.0      2.0    NIL        0
8       57  ABC 2010-02-26     0.0      2.0    NIL        0
9       58  ABC 2010-03-05     0.0      2.0    NIL        0
10      59  ABC 2010-03-12     0.0      2.0    NIL        0
11      60  ABC 2010-03-19     0.0      2.0    NIL        0
12      61  ABC 2010-03-26     0.0      2.0    NIL        0
13    1417  ABC 2010-04-02     1.0      0.0    BUY        1
14    1409  ABC 2010-04-09     1.0      0.0   HOLD        3
15      62  ABC 2010-04-23     0.0      2.0   SELL        2
16      63  ABC 2010-05-07     0.0      2.0    NIL        0
17      64  ABC 2010-05-14     0.0      2.0    NIL        0
18      65  ABC 2010-05-21     0.0      2.0    NIL        0
19      66  ABC 2010-05-28     0.0      2.0    NIL        0
 

Комментарии:

1. Спасибо, это помогло мне приблизиться на один шаг, но я дополнил вопрос некоторыми последующими задачами.

2. Эй, не беспокойтесь, я посмотрю, но вам не следовало обновлять свой первоначальный вопрос, поскольку теперь он делает мой ответ совершенно бесполезным, поскольку он делает то, что вам было нужно / о чем вы просили изначально, и в основном аннулирует мой ответ здесь (представьте себе кого-то, кто читает это впервые — мой ответ будетбыть полностью недействительным, в чем вопрос)… Я посмотрю на вашу логику, но я предложу вернуть ваш вопрос и сохранить историю. Таким образом, другие люди могут предложить вам еще лучшее общее решение. Лучше всего, если вы будете задавать по 1 вопросу за раз.. Надеюсь, это имеет смысл