Use Cases#

import onetick.py as otp

Retrieving Tick Data#

s = otp.dt(2023, 5, 15, 9, 30)
e = otp.dt(2023, 5, 15, 9, 30, 1)
trd = otp.DataSource('NYSE_TAQ', tick_type='TRD')
otp.run(trd, start=s, end=e, symbols=['SPY'])
Time EXCHANGE COND STOP_STOCK SOURCE TRF TTE TICKER PRICE DELETED_TIME TICK_STATUS SIZE CORR SEQ_NUM TRADE_ID PARTICIPANT_TIME TRF_TIME OMDSEQ
0 2023-05-15 09:30:00.000178688 P T N C 0 SPY 412.22 1969-12-31 19:00:00 0 100 0 39195 52983525167153 2023-05-15 09:30:00.000150016 1969-12-31 19:00:00.000000000 0
1 2023-05-15 09:30:00.000776704 Z N C 0 SPY 412.22 1969-12-31 19:00:00 0 247 0 39196 52983525035355 2023-05-15 09:30:00.000450000 1969-12-31 19:00:00.000000000 1
2 2023-05-15 09:30:00.003603456 T T N C 0 SPY 412.22 1969-12-31 19:00:00 0 100 0 39212 62879133157950 2023-05-15 09:30:00.003165122 1969-12-31 19:00:00.000000000 0
3 2023-05-15 09:30:00.006352128 K I N C 0 SPY 412.24 1969-12-31 19:00:00 0 1 0 39227 52983525098301 2023-05-15 09:30:00.006091000 1969-12-31 19:00:00.000000000 0
4 2023-05-15 09:30:00.007128064 K I N C 0 SPY 412.24 1969-12-31 19:00:00 0 3 0 39231 52983525098302 2023-05-15 09:30:00.006873000 1969-12-31 19:00:00.000000000 0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
310 2023-05-15 09:30:00.934032640 T T N C 0 SPY 412.27 1969-12-31 19:00:00 0 160 0 40517 62879133545538 2023-05-15 09:30:00.933678033 1969-12-31 19:00:00.000000000 1
311 2023-05-15 09:30:00.975609344 D I N C T 0 SPY 412.24 1969-12-31 19:00:00 0 2 0 40543 71675240595789 2023-05-15 09:30:00.661000000 2023-05-15 09:30:00.975241514 0
312 2023-05-15 09:30:00.980264448 D I N C T 0 SPY 412.27 1969-12-31 19:00:00 0 1 0 40545 71675240596294 2023-05-15 09:30:00.553501000 2023-05-15 09:30:00.979895700 0
313 2023-05-15 09:30:00.985391616 T N C 0 SPY 412.28 1969-12-31 19:00:00 0 100 0 40547 62879133552717 2023-05-15 09:30:00.984946104 1969-12-31 19:00:00.000000000 0
314 2023-05-15 09:30:00.985394944 T Q N C 0 SPY 412.28 1969-12-31 19:00:00 0 100 0 40549 62879133552719 2023-05-15 09:30:00.984958312 1969-12-31 19:00:00.000000000 1

315 rows × 18 columns

Creating Bars#

We create 1-minute bars (bucket_interval=60 seconds) below.

trd = otp.DataSource('NYSE_TAQ', tick_type='TRD')
trd, _ = trd[trd['COND'].str.match('^[^O6TUHILNRWZ47QMBCGPV]*$')]
bars = trd.agg({'VOLUME': otp.agg.sum('SIZE'),
                'HIGH': otp.agg.max('PRICE'),
                'LOW': otp.agg.min('PRICE'),
                'OPEN': otp.agg.first('PRICE'),
                'COUNT': otp.agg.count(),
                'CLOSE': otp.agg.last('PRICE')},
               bucket_interval=60)
otp.run(bars, start=otp.dt(2023,5,15,9,30), end=otp.dt(2023,5,15,10), symbols=['SPY'])
Time VOLUME HIGH LOW OPEN COUNT CLOSE
0 2023-05-15 09:31:00 264719 412.2900 412.0350 412.2200 1446 412.0400
1 2023-05-15 09:32:00 218724 412.2600 412.0000 412.0500 1537 412.1600
2 2023-05-15 09:33:00 271364 412.2000 411.9400 412.1650 1649 412.0200
3 2023-05-15 09:34:00 312764 412.0200 411.6312 412.0100 1827 411.8200
4 2023-05-15 09:35:00 252569 411.8300 411.3600 411.8100 1241 411.3983
5 2023-05-15 09:36:00 202980 411.6250 411.3200 411.3900 1286 411.6250
6 2023-05-15 09:37:00 114774 411.6800 411.4400 411.6200 841 411.5900
7 2023-05-15 09:38:00 152180 411.6000 411.4100 411.5800 927 411.4300
8 2023-05-15 09:39:00 96940 411.5100 411.3600 411.4300 592 411.3600
9 2023-05-15 09:40:00 129613 411.4650 411.2300 411.3550 884 411.4471
10 2023-05-15 09:41:00 111231 411.6668 411.3600 411.4550 723 411.6300
11 2023-05-15 09:42:00 214502 411.7100 411.4300 411.6400 1395 411.4750
12 2023-05-15 09:43:00 262713 411.6600 411.4200 411.4700 1379 411.4700
13 2023-05-15 09:44:00 106379 411.5200 411.3520 411.4700 654 411.4400
14 2023-05-15 09:45:00 103743 411.5250 411.4000 411.4200 551 411.5016
15 2023-05-15 09:46:00 137092 411.6600 411.5200 411.5200 871 411.6300
16 2023-05-15 09:47:00 189016 411.6900 411.3600 411.6300 1201 411.3900
17 2023-05-15 09:48:00 121331 411.4780 411.3100 411.3900 612 411.3150
18 2023-05-15 09:49:00 108976 411.3900 411.1600 411.3200 664 411.2900
19 2023-05-15 09:50:00 112394 411.3000 411.1200 411.3000 637 411.1900
20 2023-05-15 09:51:00 94153 411.2700 411.0300 411.1900 469 411.0300
21 2023-05-15 09:52:00 112302 411.1900 410.9800 411.0300 687 410.9900
22 2023-05-15 09:53:00 114025 411.1179 410.9700 410.9850 599 410.9900
23 2023-05-15 09:54:00 80763 411.1299 410.9500 410.9850 458 411.0150
24 2023-05-15 09:55:00 66556 411.1099 411.0100 411.0190 435 411.0350
25 2023-05-15 09:56:00 131143 411.1100 410.9100 411.0350 790 410.9205
26 2023-05-15 09:57:00 128274 410.9300 410.8200 410.9205 679 410.8400
27 2023-05-15 09:58:00 162243 410.9500 410.8000 410.8200 953 410.8900
28 2023-05-15 09:59:00 105649 410.9300 410.8300 410.8800 572 410.8700
29 2023-05-15 10:00:00 145019 410.9100 410.7800 410.8600 911 410.8400
Note: OneTick Cloud has minute bars precomputed and available in *_BARS databases under the tick type TRD_1M.

Daily OHLCV data with the official closing prices is also available: see OHLCV.

Note the use of apply_times_daily to limit each day’s interval to 9:30-4:00pm (plus one minute is added as the minute bar for 9:30-9:31 has the timestamp of 9:31).

bars = otp.DataSource('NYSE_TAQ_BARS', tick_type='TRD_1M')
bars = bars[['FIRST','HIGH','LOW','LAST','VOLUME']]
otp.run(bars, start=otp.dt(2023,5,15,9,31), end=otp.dt(2023,5,19,16,1), symbols=['SPY'], apply_times_daily=True)
Time FIRST HIGH LOW LAST VOLUME
0 2023-05-15 09:31:00 412.220 412.290 412.0350 412.0400 264719
1 2023-05-15 09:32:00 412.050 412.260 412.0000 412.1600 218724
2 2023-05-15 09:33:00 412.165 412.200 411.9400 412.0200 271364
3 2023-05-15 09:34:00 412.010 412.020 411.6312 411.8200 312764
4 2023-05-15 09:35:00 411.810 411.830 411.3600 411.3983 252569
... ... ... ... ... ... ...
1945 2023-05-19 15:56:00 418.890 418.950 418.8501 418.9200 465446
1946 2023-05-19 15:57:00 418.910 418.915 418.7200 418.8700 618549
1947 2023-05-19 15:58:00 418.870 418.980 418.8400 418.9500 601161
1948 2023-05-19 15:59:00 418.950 418.990 418.9000 418.9600 711607
1949 2023-05-19 16:00:00 418.960 418.970 418.5700 418.6100 1565989

1950 rows × 6 columns

Prevailing quote at the time of a trade#

trd = otp.DataSource('NYSE_TAQ', tick_type='TRD')
trd = trd[['PRICE', 'SIZE']]

qte = otp.DataSource('TAQ_NBBO', tick_type='NBBO', back_to_first_tick=600)
qte = qte[['ASK_PRICE', 'BID_PRICE']] 
qte['quote_time'] = qte['Time']

enriched_trades = otp.join_by_time([trd, qte])

otp.run(enriched_trades, start=s, end=e, symbols=['SPY'])
Time PRICE SIZE ASK_PRICE BID_PRICE quote_time
0 2023-05-15 09:30:00.000178688 412.22 100 412.25 412.22 2023-05-15 09:30:00.000174080
1 2023-05-15 09:30:00.000776704 412.22 247 412.24 412.21 2023-05-15 09:30:00.000715520
2 2023-05-15 09:30:00.003603456 412.22 100 412.24 412.22 2023-05-15 09:30:00.003562496
3 2023-05-15 09:30:00.006352128 412.24 1 412.25 412.22 2023-05-15 09:30:00.006343936
4 2023-05-15 09:30:00.007128064 412.24 3 412.25 412.22 2023-05-15 09:30:00.007110656
... ... ... ... ... ... ...
310 2023-05-15 09:30:00.934032640 412.27 160 412.28 412.26 2023-05-15 09:30:00.934030080
311 2023-05-15 09:30:00.975609344 412.24 2 412.28 412.27 2023-05-15 09:30:00.970691840
312 2023-05-15 09:30:00.980264448 412.27 1 412.28 412.27 2023-05-15 09:30:00.979763456
313 2023-05-15 09:30:00.985391616 412.28 100 412.28 412.27 2023-05-15 09:30:00.985296640
314 2023-05-15 09:30:00.985394944 412.28 100 412.28 412.27 2023-05-15 09:30:00.985296640

315 rows × 6 columns

Point-in-time benchmarks: BBO at different markouts#

Now let’s find the prevailing quote at different time intervals (markouts) before/after each trade.

markouts = [-1, 0, 1, 5, 60, 600] 

trd = otp.DataSource('NYSE_TAQ', tick_type='TRD')
trd = trd[['PRICE', 'SIZE']]

qte_by_markout = []
for m in markouts:
    qte = otp.DataSource('TAQ_NBBO', tick_type='NBBO', back_to_first_tick=86400)
    qte = qte[['ASK_PRICE', 'BID_PRICE']]
    qte = qte.rename({'ASK_PRICE': f'ASK_PRICE_{m}', 
                      'BID_PRICE': f'BID_PRICE_{m}'})
    qte[f'quote_time_{m}'] = qte['Time']
    
    # shift the data by m seconds
    qte = qte.time_interval_shift(m * 1000)
    qte_by_markout.append(qte)

trd = otp.join_by_time([trd] + qte_by_markout)
otp.run(trd, start=s, end=e, symbols=['SPY'], apply_times_daily=True)
Time PRICE SIZE ASK_PRICE_-1 BID_PRICE_-1 quote_time_-1 ASK_PRICE_0 BID_PRICE_0 quote_time_0 ASK_PRICE_1 BID_PRICE_1 quote_time_1 ASK_PRICE_5 BID_PRICE_5 quote_time_5 ASK_PRICE_60 BID_PRICE_60 quote_time_60 ASK_PRICE_600 BID_PRICE_600 quote_time_600
0 2023-05-15 09:30:00.000178688 412.22 100 412.26 412.23 2023-05-15 09:29:59.000000000 412.25 412.22 2023-05-15 09:30:00.000174080 412.28 412.27 2023-05-15 09:30:01.000000000 412.23 412.21 2023-05-15 09:30:05.000000000 412.06 412.05 2023-05-15 09:31:00.000105984 411.45 411.44 2023-05-15 09:40:00.000000000
1 2023-05-15 09:30:00.000776704 412.22 247 412.26 412.23 2023-05-15 09:29:59.000000000 412.24 412.21 2023-05-15 09:30:00.000715520 412.28 412.27 2023-05-15 09:30:01.000000000 412.23 412.21 2023-05-15 09:30:05.000000000 412.06 412.05 2023-05-15 09:31:00.000772608 411.45 411.44 2023-05-15 09:40:00.000000000
2 2023-05-15 09:30:00.003603456 412.22 100 412.26 412.23 2023-05-15 09:29:59.000000000 412.24 412.22 2023-05-15 09:30:00.003562496 412.28 412.27 2023-05-15 09:30:01.002818816 412.23 412.21 2023-05-15 09:30:05.000000000 412.06 412.05 2023-05-15 09:31:00.001634816 411.45 411.44 2023-05-15 09:40:00.000000000
3 2023-05-15 09:30:00.006352128 412.24 1 412.26 412.23 2023-05-15 09:29:59.005259520 412.25 412.22 2023-05-15 09:30:00.006343936 412.28 412.27 2023-05-15 09:30:01.004251904 412.23 412.21 2023-05-15 09:30:05.000000000 412.06 412.05 2023-05-15 09:31:00.005624320 411.45 411.44 2023-05-15 09:40:00.006328576
4 2023-05-15 09:30:00.007128064 412.24 3 412.26 412.23 2023-05-15 09:29:59.007053824 412.25 412.22 2023-05-15 09:30:00.007110656 412.28 412.27 2023-05-15 09:30:01.004251904 412.23 412.21 2023-05-15 09:30:05.000000000 412.05 412.04 2023-05-15 09:31:00.007117824 411.45 411.44 2023-05-15 09:40:00.007125760
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
310 2023-05-15 09:30:00.934032640 412.27 160 412.26 412.22 2023-05-15 09:29:59.837682688 412.28 412.26 2023-05-15 09:30:00.934030080 412.28 412.26 2023-05-15 09:30:01.931170560 412.25 412.23 2023-05-15 09:30:05.898093824 412.07 412.06 2023-05-15 09:31:00.927816448 411.44 411.43 2023-05-15 09:40:00.928655104
311 2023-05-15 09:30:00.975609344 412.24 2 412.25 412.22 2023-05-15 09:29:59.970543872 412.28 412.27 2023-05-15 09:30:00.970691840 412.29 412.26 2023-05-15 09:30:01.972468480 412.25 412.24 2023-05-15 09:30:05.973397760 412.07 412.06 2023-05-15 09:31:00.972016640 411.44 411.43 2023-05-15 09:40:00.954621952
312 2023-05-15 09:30:00.980264448 412.27 1 412.25 412.22 2023-05-15 09:29:59.970543872 412.28 412.27 2023-05-15 09:30:00.979763456 412.29 412.27 2023-05-15 09:30:01.978472704 412.26 412.24 2023-05-15 09:30:05.978229504 412.07 412.06 2023-05-15 09:31:00.972016640 411.44 411.43 2023-05-15 09:40:00.954621952
313 2023-05-15 09:30:00.985391616 412.28 100 412.25 412.22 2023-05-15 09:29:59.970543872 412.28 412.27 2023-05-15 09:30:00.985296640 412.29 412.27 2023-05-15 09:30:01.985324032 412.26 412.24 2023-05-15 09:30:05.978229504 412.07 412.06 2023-05-15 09:31:00.972016640 411.44 411.43 2023-05-15 09:40:00.954621952
314 2023-05-15 09:30:00.985394944 412.28 100 412.25 412.22 2023-05-15 09:29:59.970543872 412.28 412.27 2023-05-15 09:30:00.985296640 412.29 412.27 2023-05-15 09:30:01.985324032 412.26 412.24 2023-05-15 09:30:05.978229504 412.07 412.06 2023-05-15 09:31:00.972016640 411.44 411.43 2023-05-15 09:40:00.954621952

315 rows × 21 columns

Interval Metrics (e.g., VWAP)#

q = otp.DataSource('NYSE_TAQ', tick_type='TRD')
q = q.agg({'market_vwap': otp.agg.vwap('PRICE', 'SIZE')})
otp.run(q, start=s, end=e, symbols=['SPY'])
Time market_vwap
0 2023-05-15 09:30:01 412.212012

Computing market VWAP for every order’s arrival/exit interval#

orders = otp.Ticks(arrival=[s, s+otp.Milli(7934)], 
                   exit=[e, e+otp.Milli(2556)],
                   sym=['SPY', 'QQQ'])
otp.run(orders, start=s, end=s+otp.Day(1))
Time arrival exit sym
0 2023-05-15 09:30:00.000 2023-05-15 09:30:00.000 2023-05-15 09:30:01.000 SPY
1 2023-05-15 09:30:00.001 2023-05-15 09:30:07.934 2023-05-15 09:30:03.556 QQQ
def vwap(symbol):
    q = otp.DataSource('NYSE_TAQ', tick_type='TRD')
    q = q.agg({'market_vwap': otp.agg.vwap('PRICE','SIZE')})
    return q

orders = otp.Ticks(arrival=[s, s+otp.Milli(7934)], 
                   exit=[e, e+otp.Milli(9556)],
                   sym=['SPY', 'QQQ'])
orders = orders.join_with_query(vwap, start=orders['arrival'], end=orders['exit'], symbol=orders['sym'])
otp.run(orders, start=s, end=s+otp.Day(1))
Time market_vwap arrival exit sym
0 2023-05-15 09:30:00.000 412.212012 2023-05-15 09:30:00.000 2023-05-15 09:30:01.000 SPY
1 2023-05-15 09:30:00.001 325.318988 2023-05-15 09:30:07.934 2023-05-15 09:30:10.556 QQQ

A more efficient implementation is also available with symbol parameters.

Real-time processing: Signal Generation#

We’ll compute golden cross signals using 50-second and 200-second moving averages

  • ‘Entries’ is set to 1 when the short-term moving average goes above the long term (i.e., a signal to buy)

  • ‘Exits’ is set to 1 on when the short-term moving average goes below the long term (i.e., a signal to sell)

trd = otp.DataSource('NYSE_TAQ', tick_type='TRD')
trd = trd[['PRICE']]

trd = trd.agg({'short': otp.agg.mean('PRICE')}, bucket_interval=60, running=True, all_fields=True)
trd = trd.agg({'long': otp.agg.mean('PRICE')}, bucket_interval=60*5, running=True, all_fields=True)

trd['buy'] = (trd['short'][-1] < trd['long'][-1]) & (trd['short'] > trd['long']) 
trd['sell'] = (trd['short'][-1] > trd['long'][-1]) & (trd['short'] < trd['long']) 

We define a callback that for every tick (i.e., on every trade) will

  • print a ‘.’ if there is no signal

  • print out the tick followed by ‘BUY’ on an entry signal

  • print out the tick followed by ‘SELL’ on an exit signal

class GoldenCrossCallback(otp.CallbackBase):
    def process_tick(self, tick, time):
        if not tick['buy'] and not tick['sell']:
            print('.', end='')
            return
        print()
        print()
        print(time, tick)
        if tick['buy']:
            print('BUY')
        if tick['sell']:
            print('SELL')
        print()

The query will run continuously with the output printed as the events happen if you set start/end times accordingly (see the commented out line).

# timestamps appear in GMT
cb = GoldenCrossCallback()
otp.run(trd, symbols=['SPY'],
        callback=cb, running=True,
        # start=otp.dt.now(), end=otp.dt.now() + otp.Day(1),
        start=otp.dt(2023, 3, 31, 10), end=otp.dt(2023, 3, 31, 10, 5),
)
..................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................

2023-03-31 14:02:16.717255 {'PRICE': 405.54, 'short': 405.70794973568997, 'long': 405.70836495181135, 'buy': 0.0, 'sell': 1.0}
SELL

............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
.....................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................

Upticks / Downticks#

Let’s mark each trade as an uptick if its price is above the last trade’s price and as a downtick if it’s below.

def uptick(t):
    if t['PRICE'] == otp.nan or t['PRICE'][-1] == otp.nan:
        return otp.nan
    if t['PRICE'] > t['PRICE'][-1]:
        return 1
    elif t['PRICE'] < t['PRICE'][-1]:
        return -1
    else:
        return 0

trd = otp.DataSource('NYSE_TAQ', tick_type='TRD')
trd = trd[['PRICE']]
trd['UPTICK'] = trd.apply(uptick)
otp.run(trd, start=s, end=e, symbols=['SPY'])
Time PRICE UPTICK
0 2023-05-15 09:30:00.000178688 412.22 NaN
1 2023-05-15 09:30:00.000776704 412.22 0.0
2 2023-05-15 09:30:00.003603456 412.22 0.0
3 2023-05-15 09:30:00.006352128 412.24 1.0
4 2023-05-15 09:30:00.007128064 412.24 0.0
... ... ... ...
310 2023-05-15 09:30:00.934032640 412.27 0.0
311 2023-05-15 09:30:00.975609344 412.24 -1.0
312 2023-05-15 09:30:00.980264448 412.27 1.0
313 2023-05-15 09:30:00.985391616 412.28 1.0
314 2023-05-15 09:30:00.985394944 412.28 0.0

315 rows × 3 columns