Variables and Data Structures#

import onetick.py as otp
from datetime import datetime
otp.config['default_start_time'] = datetime(2003, 12, 1, 0, 0, 0)
otp.config['default_end_time'] = datetime(2003, 12, 4, 0, 0, 0)
otp.config['default_db'] = 'DEMO_L1'
otp.config['default_symbol'] = 'AAPL'

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