Variables and Data Structures#

import onetick.py as otp

We can use variables to keep track of a state across trd. The example below shows how we may keep track of P&L.

trd = otp.Ticks({'PRICE': [13.5, 13.6, 13.3, 14.0],
                 'SIZE': [200, 100, 150, 200],
                 'SIDE': ['B', 'S', 'B', 'S']})

trd.state_vars['PROFIT'] = 0
trd.state_vars['PROFIT'] += trd.apply(
    lambda t: t['PRICE'] * t['SIZE'] if t['SIDE'] == 'S' else -(t['PRICE'] * t['SIZE'])
)

trd['PROFIT'] = trd.state_vars['PROFIT']

otp.run(trd)
Time PRICE SIZE SIDE PROFIT
0 2003-12-01 00:00:00.000 13.5 200 B -2700
1 2003-12-01 00:00:00.001 13.6 100 S -1340
2 2003-12-01 00:00:00.002 13.3 150 B -3335
3 2003-12-01 00:00:00.003 14.0 200 S -535

Let’s take a look at what the code above does: the variable ‘PROFIT’ keeps a running total. In other words, it aggregates state across trd.

An alternative implementation might avoid using variables by keeping the running total in a separate column. Let’s try implementing that.

trd = otp.Ticks({'PRICE': [13.5, 13.6, 13.3, 14.0],
                 'SIZE': [200, 100, 150, 200],
                 'SIDE': ['B', 'S', 'B', 'S']})
trd['VALUE'] = trd.apply(
    lambda t: t['PRICE'] * t['SIZE'] if t['SIDE'] == 'S' else -(t['PRICE'] * t['SIZE'])
)
trd = trd.agg({'PROFIT': otp.agg.sum('VALUE')}, running=True)
otp.run(trd)
Time PROFIT
0 2003-12-01 00:00:00.000 -2700.0
1 2003-12-01 00:00:00.001 -1340.0
2 2003-12-01 00:00:00.002 -3335.0
3 2003-12-01 00:00:00.003 -535.0

Another use case is to store the value from the last tick during aggregation / grouping.

q = otp.Ticks(X=[-1, 3, -3, 4, 2], Y=[0, 1, 1, 0, 3])
q.state_vars['S'] = 0
q.state_vars['S'] = q['X']
q = q.high('X', group_by=['Y'])
q['S'] = q.state_vars['S']
otp.run(q)
Time X Y S
0 2003-12-01 00:00:00.001 3 1 2
1 2003-12-01 00:00:00.003 4 0 2
2 2003-12-01 00:00:00.004 2 3 2