Как рассчитать средневзвешенную цену по объему (VWAP), используя фрейм данных pandas с ценой спроса и предложения? - PullRequest
2 голосов
/ 16 апреля 2019

Как создать еще один столбец с именем vwap, который вычисляет значение vwap, если моя таблица выглядит так, как показано ниже?

             time            bid_size   bid       ask  ask_size trade trade_size phase  
0   2019-01-07 07:45:01.064515  495   152.52    152.54    19     NaN      NaN    OPEN   
1   2019-01-07 07:45:01.110072  31    152.53    152.54    19     NaN      NaN    OPEN   
2   2019-01-07 07:45:01.116596  32    152.53    152.54    19     NaN      NaN    OPEN   
3   2019-01-07 07:45:01.116860  32    152.53    152.54    21     NaN      NaN    OPEN   
4   2019-01-07 07:45:01.116905  34    152.53    152.54    21     NaN      NaN    OPEN   
5   2019-01-07 07:45:01.116982  34    152.53    152.54    31     NaN      NaN    OPEN   
6   2019-01-07 07:45:01.147901  38    152.53    152.54    31     NaN      NaN    OPEN   
7   2019-01-07 07:45:01.189971  38    152.53    152.54    31     ask     15.0    OPEN   
8   2019-01-07 07:45:01.189971  38    152.53    152.54    16     NaN      NaN    OPEN   
9   2019-01-07 07:45:01.190766  37    152.53    152.54    16     NaN      NaN    OPEN   
10  2019-01-07 07:45:01.190856  37    152.53    152.54    15     NaN      NaN    OPEN
11  2019-01-07 07:45:01.190856  37    152.53    152.54    16     ask      1.0    OPEN   
12  2019-01-07 07:45:01.193938  37    152.53    152.55   108     NaN      NaN    OPEN   
13  2019-01-07 07:45:01.193938  37    152.53    152.54    15     ask     15.0    OPEN   
14  2019-01-07 07:45:01.194326  2     152.54    152.55   108     NaN      NaN    OPEN   
15  2019-01-07 07:45:01.194453  2     152.54    152.55    97     NaN      NaN    OPEN   
16  2019-01-07 07:45:01.194479  6     152.54    152.55    97     NaN      NaN    OPEN   
17  2019-01-07 07:45:01.194507  19    152.54    152.55    97     NaN      NaN    OPEN   
18  2019-01-07 07:45:01.194532  19    152.54    152.55    77     NaN      NaN    OPEN   
19  2019-01-07 07:45:01.194598  19    152.54    152.55    79     NaN      NaN    OPEN   

Извините, таблица не понятна, но второй самый правый столбец - trade_size, onслева - торговля, которая показывает сторону сделки (бид или аск).если как trade_size, так и trade равны NaN, это указывает на то, что в этот момент времени сделки не происходит.

Если df ['trade'] == "ask", цена сделки будет являться ценой в столбце ask, а еслиdf ['trade] == "bid", цена сделки будет указана в столбце bid.Поскольку существует 2 цены, могу я спросить, как я могу рассчитать vwap, df ['vwap']?

Моя идея - использовать np.cumsum ().Спасибо!

Ответы [ 3 ]

1 голос
/ 16 апреля 2019

Хорошо, вот оно

df['trade_price'] = df.apply(lambda x: x['bid'] if x['trade']=='bid' else x['ask'], axis=1)
df['vwap'] = (df['trade_price'] * df['trade_size']).cumsum() / df['trade_size'].fillna(0).cumsum()

Первая строка:
Он сохраняет trade_price в новом столбце, поэтому его проще получить позже.
Если вы хотите, вы можете удалить эту строку и сделать функцию (возможно, ее легче читать). Но я предпочитаю видеть промежуточные результаты.
Вопрос: почему он имеет значения, даже когда нет торговли?
A: из-за того, как написана лямбда. else захватывает цену ask. Но это не будет иметь значения из-за следующего шага.

Вторая строка:
Здесь происходит реальный расчет.
В первой части рассчитывается общий объем торгов до этого момента (как вы сказали, использование кумулятивных сумм облегчает жизнь).
Вторая часть вычисляет общий объем торгов до этого момента (опять же, кумулятивные суммы).
Если хотите, можете разбить эту строку и создать дополнительные промежуточные столбцы.
Q: почему fillna(0)?
A: таким образом, общий объем не получится NaNs, и вы не получите ошибку деления В: почему так много NaNs в столбце vwap?
A: Из-за линий, у которых нет торговли. Вы можете заполнить их 0s, но было бы лучше сохранить информацию об отсутствии торговли.

Ps .: вы можете получить неправильный результат, так как он учитывает объем и цену только в одном направлении. Но вы можете попытаться инвертировать некоторый сигнал, чтобы зафиксировать объем так, как вы ожидаете (например: изменение цены ask на отрицательную).

и вывод этого кода:

    trade_price vwap
1   152.54  NaN
2   152.54  NaN
3   152.54  NaN
4   152.54  NaN
5   152.54  NaN
6   152.54  NaN
7   152.54  NaN
8   152.54  152.54
9   152.54  NaN
10  152.54  NaN
11  152.54  NaN
12  152.54  152.54
13  152.55  NaN
14  152.54  152.54
15  152.55  NaN
16  152.55  NaN
17  152.55  NaN
18  152.55  NaN
19  152.55  NaN
20  152.55  NaN
1 голос
/ 18 апреля 2019

Вы можете использовать np.where, чтобы указать цену из правильного столбца (bid или ask) в зависимости от значения в столбце trade.Обратите внимание, что это дает вам цену покупки, когда сделки не происходит, но, поскольку она затем умножается на NaN размер сделки, это не имеет значения.Я также вперед заполнил VWAP.

volume = df['trade_size']
price = np.where(df['trade'].eq('ask'), df['ask'], df['bid'])  
df = df.assign(VWAP=((volume * price).cumsum() / vol.cumsum()).ffill())

>>> df
        time    bid_size    bid ask ask_size    trade   trade_size  phase   VWAP
0   2019-01-07  07:45:01.064515 495 152.52  152.54  19  NaN NaN OPEN    NaN
1   2019-01-07  07:45:01.110072 31  152.53  152.54  19  NaN NaN OPEN    NaN
2   2019-01-07  07:45:01.116596 32  152.53  152.54  19  NaN NaN OPEN    NaN
3   2019-01-07  07:45:01.116860 32  152.53  152.54  21  NaN NaN OPEN    NaN
4   2019-01-07  07:45:01.116905 34  152.53  152.54  21  NaN NaN OPEN    NaN
5   2019-01-07  07:45:01.116982 34  152.53  152.54  31  NaN NaN OPEN    NaN
6   2019-01-07  07:45:01.147901 38  152.53  152.54  31  NaN NaN OPEN    NaN
7   2019-01-07  07:45:01.189971 38  152.53  152.54  31  ask 15.0    OPEN    152.54
8   2019-01-07  07:45:01.189971 38  152.53  152.54  16  NaN NaN OPEN    152.54
9   2019-01-07  07:45:01.190766 37  152.53  152.54  16  NaN NaN OPEN    152.54
10  2019-01-07  07:45:01.190856 37  152.53  152.54  15  NaN NaN OPEN    152.54
11  2019-01-07  07:45:01.190856 37  152.53  152.54  16  ask 1.0 OPEN    152.54
12  2019-01-07  07:45:01.193938 37  152.53  152.55  108 NaN NaN OPEN    152.54
13  2019-01-07  07:45:01.193938 37  152.53  152.54  15  ask 15.0    OPEN    152.54
14  2019-01-07  07:45:01.194326 2   152.54  152.55  108 NaN NaN OPEN    152.54
15  2019-01-07  07:45:01.194453 2   152.54  152.55  97  NaN NaN OPEN    152.54
16  2019-01-07  07:45:01.194479 6   152.54  152.55  97  NaN NaN OPEN    152.54
17  2019-01-07  07:45:01.194507 19  152.54  152.55  97  NaN NaN OPEN    152.54
18  2019-01-07  07:45:01.194532 19  152.54  152.55  77  NaN NaN OPEN    152.54
19  2019-01-07  07:45:01.194598 19  152.54  152.55  79  NaN NaN OPEN    152.54
1 голос
/ 16 апреля 2019

Вот один из возможных подходов

Добавить VMAP столбец, заполненный NaN s

df['VMAP'] = np.nan

Рассчитать VMAP (на основе это уравнение предоставляется OP ) и присваивает значения на основе ask или bid, в соответствии с запросом OP

for trade in ['ask','bid']:
    # Find indexes of `ask` or `buy`
    bid_idx = df[df.trade==trade].index

    # Slice DF based on `ask` or `buy`, using indexes
    df.loc[bid_idx, 'VMAP'] = (
        (df.loc[bid_idx, 'trade_size'] * df.loc[bid_idx, trade]).cumsum()
        /
        (df.loc[bid_idx, 'trade_size']).cumsum()
                )

print(df.iloc[:,1:])
               time  bid_size     bid     ask  ask_size trade  trade_size phase    VMAP
0   07:45:01.064515       495  152.52  152.54        19   NaN         NaN  OPEN     NaN
1   07:45:01.110072        31  152.53  152.54        19   NaN         NaN  OPEN     NaN
2   07:45:01.116596        32  152.53  152.54        19   NaN         NaN  OPEN     NaN
3   07:45:01.116860        32  152.53  152.54        21   NaN         NaN  OPEN     NaN
4   07:45:01.116905        34  152.53  152.54        21   NaN         NaN  OPEN     NaN
5   07:45:01.116982        34  152.53  152.54        31   NaN         NaN  OPEN     NaN
6   07:45:01.147901        38  152.53  152.54        31   NaN         NaN  OPEN     NaN
7   07:45:01.189971        38  152.53  152.54        31   ask        15.0  OPEN  152.54
8   07:45:01.189971        38  152.53  152.54        16   NaN         NaN  OPEN     NaN
9   07:45:01.190766        37  152.53  152.54        16   NaN         NaN  OPEN     NaN
10  07:45:01.190856        37  152.53  152.54        15   NaN         NaN  OPEN     NaN
11  07:45:01.190856        37  152.53  152.54        16   ask         1.0  OPEN  152.54
12  07:45:01.193938        37  152.53  152.55       108   NaN         NaN  OPEN     NaN
13  07:45:01.193938        37  152.53  152.54        15   ask        15.0  OPEN  152.54
14  07:45:01.194326         2  152.54  152.55       108   NaN         NaN  OPEN     NaN
15  07:45:01.194453         2  152.54  152.55        97   NaN         NaN  OPEN     NaN
16  07:45:01.194479         6  152.54  152.55        97   NaN         NaN  OPEN     NaN
17  07:45:01.194507        19  152.54  152.55        97   NaN         NaN  OPEN     NaN
18  07:45:01.194532        19  152.54  152.55        77   NaN         NaN  OPEN     NaN
19  07:45:01.194598        19  152.54  152.55        79   NaN         NaN  OPEN     NaN

EDIT

Если @edinho правильно указано , VMAP соответствует столбцу trade_price.

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