Participation weighted price (PWP)#

The PWP is calculated as the market VWAP of trades starting from the order arrival time up to the trade that reaches the cumulative volume of y/x, where y is the order quantity and x is the participation percentage. Here’s how it’s done:

import onetick.py as otp

# Define your symbols, orders database, and date
symbol = 'TSLA'
orders_db = 'ORDERS_DB'
date = otp.dt(2022, 3, 2)
trades_db = 'NYSE_TAQ'

# Participation ratios
ratios = [0.01, 0.03, 0.07]

def pwp_query(volume):
    """ Function to find necessary VWAP based on the qty of the order."""
    # Get trades from the specified trades database
    trades = otp.DataSource(db=trades_db, tick_type='TRD')
    trades = trades.table(**{'PRICE': float, 'SIZE': int})

    # Aggregate trades to get VWAP using running aggregation
    trades = trades.agg({'VWAP': otp.agg.vwap(price_column='PRICE', size_column='SIZE'),
                         'VOLUME': otp.agg.sum('SIZE')},
                        running=True,
                        all_fields=True)

    # Calculate PWP for each ratio
    for ratio in ratios:
        state_name = str(ratio).replace('.', '')
        trades.state_vars[state_name] = otp.state.var(otp.nan, scope='all_outputs')

        trades = trades.update({
                trades.state_vars[state_name]: trades['VWAP'],
            }, where=(trades['VOLUME'] <= volume / ratio))

    # Get the last trade to save results from state variables
    res = trades.last(keep_timestamp=False)
    to_output = []
    for ratio in ratios:
        pwp_name = 'PWP_' + str(ratio).replace('.', '_')
        state_name = str(ratio).replace('.', '')

        # Put values from state variables into resulting tick
        res[pwp_name] = res.state_vars[state_name]
        to_output.append(pwp_name)

    res = res[to_output]
    return res

# Load orders data
orders = otp.DataSource(db=orders_db, tick_type='ORDER', symbol=symbol)

# Aggregate orders to calculate total executed quantity and arrival time
orders_agg = orders.agg({'QTY_FILLED': otp.agg.sum('QTY_FILLED'),
                         'ARRIVAL_TIME': otp.agg.first_time()},
                         group_by='ID')

# Join PWP values to every order using total order executed value (QTY_FILLED)
# starting from the ARRIVAL_TIME. The logic in `pwp_query` accumulates ticks
# until it reaches the necessary market volume.
result = orders_agg.join_with_query(pwp_query,
                                    params={'volume': orders_agg['QTY_FILLED']},
                                    start=orders_agg['ARRIVAL_TIME'])

# Run the query for the specified date
df = otp.run(result, date=date)