Use Cases#
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'] = 'NYSE_TAQ'
otp.config['default_symbol'] = 'AAPL'
otp.config['tz'] = 'EST5EDT'
Retrieving Tick Data#
trd = otp.DataSource('NYSE_TAQ', tick_type='TRD')
otp.run(trd, start=otp.dt(2023,4,20,9,30), end=otp.dt(2023,4,20,9,35), 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-04-20 09:30:00.000650240 | Z | N | C | 0 | SPY | 411.2100 | 1969-12-31 19:00:00 | 0 | 231 | 0 | 78367 | 52983525042744 | 2023-04-20 09:30:00.000331000 | 1969-12-31 19:00:00.000000000 | 0 | ||
1 | 2023-04-20 09:30:00.000656384 | T | T | N | C | 0 | SPY | 411.2000 | 1969-12-31 19:00:00 | 0 | 100 | 0 | 78368 | 62879146921029 | 2023-04-20 09:30:00.000273283 | 1969-12-31 19:00:00.000000000 | 1 | |
2 | 2023-04-20 09:30:00.002436608 | K | N | C | 0 | SPY | 411.2000 | 1969-12-31 19:00:00 | 0 | 400 | 0 | 78373 | 52983525173819 | 2023-04-20 09:30:00.002089000 | 1969-12-31 19:00:00.000000000 | 0 | ||
3 | 2023-04-20 09:30:00.002562816 | Z | F I | N | C | 1 | SPY | 411.2100 | 1969-12-31 19:00:00 | 0 | 50 | 0 | 78374 | 52983525042745 | 2023-04-20 09:30:00.002325000 | 1969-12-31 19:00:00.000000000 | 1 | |
4 | 2023-04-20 09:30:00.002568960 | Z | F I | N | C | 1 | SPY | 411.2200 | 1969-12-31 19:00:00 | 0 | 50 | 0 | 78375 | 52983525042746 | 2023-04-20 09:30:00.002325000 | 1969-12-31 19:00:00.000000000 | 2 | |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
17115 | 2023-04-20 09:34:59.781732352 | P | F | N | C | 1 | SPY | 411.7400 | 1969-12-31 19:00:00 | 0 | 100 | 0 | 119251 | 52983525623877 | 2023-04-20 09:34:59.781707776 | 1969-12-31 19:00:00.000000000 | 0 | |
17116 | 2023-04-20 09:34:59.781930752 | K | F | N | C | 1 | SPY | 411.7400 | 1969-12-31 19:00:00 | 0 | 100 | 0 | 119252 | 52983525236544 | 2023-04-20 09:34:59.781680000 | 1969-12-31 19:00:00.000000000 | 1 | |
17117 | 2023-04-20 09:34:59.892375040 | Z | I | N | C | 0 | SPY | 411.7400 | 1969-12-31 19:00:00 | 0 | 40 | 0 | 119268 | 52983525106510 | 2023-04-20 09:34:59.892138000 | 1969-12-31 19:00:00.000000000 | 0 | |
17118 | 2023-04-20 09:34:59.930526464 | D | N | C | T | 0 | SPY | 411.7425 | 1969-12-31 19:00:00 | 0 | 200 | 0 | 119270 | 71675308169546 | 2023-04-20 09:34:59.780763000 | 2023-04-20 09:34:59.930170219 | 0 | |
17119 | 2023-04-20 09:34:59.958385152 | Z | N | C | 0 | SPY | 411.7400 | 1969-12-31 19:00:00 | 0 | 160 | 0 | 119271 | 52983525106514 | 2023-04-20 09:34:59.958147000 | 1969-12-31 19:00:00.000000000 | 0 |
17120 rows × 18 columns
Creating Bars#
We create 10-minute bars (bucket_interval=600
seconds) below.
trd = otp.DataSource('NYSE_TAQ', tick_type='TRD')
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=600)
otp.run(bars, start=otp.dt(2022,11,28,9,30), end=otp.dt(2022,11,30,16), symbols=['AA'], apply_times_daily=True)
Time | VOLUME | HIGH | LOW | OPEN | COUNT | CLOSE | |
---|---|---|---|---|---|---|---|
0 | 2022-11-28 09:40:00 | 256335 | 47.3400 | 46.4110 | 46.9200 | 1958 | 47.2000 |
1 | 2022-11-28 09:50:00 | 103989 | 47.3100 | 46.9050 | 47.1800 | 1360 | 47.1399 |
2 | 2022-11-28 10:00:00 | 96622 | 47.2400 | 46.9600 | 47.0900 | 1102 | 47.0900 |
3 | 2022-11-28 10:10:00 | 169139 | 47.1600 | 46.7400 | 47.1000 | 1770 | 46.9113 |
4 | 2022-11-28 10:20:00 | 115764 | 47.3000 | 46.7800 | 46.9100 | 1230 | 47.1250 |
... | ... | ... | ... | ... | ... | ... | ... |
112 | 2022-11-30 15:20:00 | 215528 | 50.1100 | 49.7319 | 49.7716 | 2118 | 49.9711 |
113 | 2022-11-30 15:30:00 | 146682 | 50.3100 | 49.9400 | 49.9750 | 2127 | 50.2800 |
114 | 2022-11-30 15:40:00 | 188976 | 50.5000 | 50.2300 | 50.2700 | 2624 | 50.2300 |
115 | 2022-11-30 15:50:00 | 200605 | 50.3561 | 50.0100 | 50.2300 | 3231 | 50.0700 |
116 | 2022-11-30 16:00:00 | 581342 | 50.1900 | 49.8300 | 50.0700 | 6493 | 50.1400 |
117 rows × 7 columns
Daily OHLCV data with the official closing prices is also available: see OHLCV.
bars = otp.DataSource('NYSE_TAQ_BARS', tick_type='TRD_1M')
bars = bars[['FIRST','HIGH','LOW','LAST','VOLUME']]
otp.run(bars, start=otp.dt(2022,11,28,9,31), end=otp.dt(2022,11,30,16,1), symbols=['SPY'], apply_times_daily=True)
Time | FIRST | HIGH | LOW | LAST | VOLUME | |
---|---|---|---|---|---|---|
0 | 2022-11-28 09:31:00 | 399.09 | 399.750 | 399.000 | 399.6500 | 289791 |
1 | 2022-11-28 09:32:00 | 399.69 | 400.000 | 399.600 | 399.8900 | 295441 |
2 | 2022-11-28 09:33:00 | 399.89 | 400.175 | 399.840 | 400.1750 | 233032 |
3 | 2022-11-28 09:34:00 | 400.16 | 400.380 | 400.000 | 400.1600 | 208954 |
4 | 2022-11-28 09:35:00 | 400.13 | 400.360 | 400.120 | 400.3493 | 112015 |
... | ... | ... | ... | ... | ... | ... |
1165 | 2022-11-30 15:56:00 | 406.68 | 406.830 | 406.460 | 406.8100 | 1311316 |
1166 | 2022-11-30 15:57:00 | 406.80 | 406.830 | 406.525 | 406.6000 | 1319798 |
1167 | 2022-11-30 15:58:00 | 406.60 | 406.850 | 406.550 | 406.7300 | 1691348 |
1168 | 2022-11-30 15:59:00 | 406.73 | 406.950 | 406.680 | 406.7100 | 2592503 |
1169 | 2022-11-30 16:00:00 | 406.71 | 407.550 | 406.680 | 407.4700 | 6700757 |
1170 rows × 6 columns
Prevailing quote at the time of a trade#
import onetick.py as otp
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=otp.dt(2023,4,20,9,30), end=otp.dt(2023,4,20,10), symbols='SPY')
Time | PRICE | SIZE | ASK_PRICE | BID_PRICE | quote_time | |
---|---|---|---|---|---|---|
0 | 2023-04-20 09:30:00.000650240 | 411.21 | 231 | 411.22 | 411.20 | 2023-04-20 09:30:00.000636672 |
1 | 2023-04-20 09:30:00.000656384 | 411.20 | 100 | 411.22 | 411.20 | 2023-04-20 09:30:00.000636672 |
2 | 2023-04-20 09:30:00.002436608 | 411.20 | 400 | 411.22 | 411.20 | 2023-04-20 09:30:00.002411008 |
3 | 2023-04-20 09:30:00.002562816 | 411.21 | 50 | 411.22 | 411.20 | 2023-04-20 09:30:00.002486016 |
4 | 2023-04-20 09:30:00.002568960 | 411.22 | 50 | 411.22 | 411.20 | 2023-04-20 09:30:00.002566912 |
... | ... | ... | ... | ... | ... | ... |
63773 | 2023-04-20 09:59:59.967479808 | 411.66 | 100 | 411.67 | 411.65 | 2023-04-20 09:59:59.967476224 |
63774 | 2023-04-20 09:59:59.971563520 | 411.66 | 100 | 411.67 | 411.66 | 2023-04-20 09:59:59.971560960 |
63775 | 2023-04-20 09:59:59.971569408 | 411.66 | 100 | 411.67 | 411.66 | 2023-04-20 09:59:59.971565824 |
63776 | 2023-04-20 09:59:59.971674624 | 411.66 | 100 | 411.67 | 411.66 | 2023-04-20 09:59:59.971671296 |
63777 | 2023-04-20 09:59:59.972700160 | 411.68 | 1 | 411.67 | 411.65 | 2023-04-20 09:59:59.971976960 |
63778 rows × 6 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=otp.dt(2023,4,10,10,25,59), end=otp.dt(2023,4,10,10,27), symbols='AAPL')
Time | market_vwap | |
---|---|---|
0 | 2023-04-10 10:27:00 | 160.477922 |
Computing market VWAP for every order’s arrival/exit interval#
orders = otp.Ticks(arrival=[otp.dt(2023,4,10,10,25,59), otp.dt(2023,4,10,10,26,9)],
exit=[otp.dt(2023,4,10,10,26,7), otp.dt(2023,4,10,10,27,48)],
sym=['AAPL', 'MSFT'])
otp.run(orders)
Time | arrival | exit | sym | |
---|---|---|---|---|
0 | 2003-12-01 00:00:00.000 | 2023-04-10 10:25:59 | 2023-04-10 10:26:07 | AAPL |
1 | 2003-12-01 00:00:00.001 | 2023-04-10 10:26:09 | 2023-04-10 10:27:48 | MSFT |
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=[otp.dt(2023,4,10,10,25,59), otp.dt(2023,4,10,10,26,9)],
exit=[otp.dt(2023,4,10,10,26,7), otp.dt(2023,4,10,10,27,48)],
sym=['AAPL', 'MSFT'])
orders = orders.join_with_query(vwap, start=orders['arrival'], end=orders['exit'], symbol=orders['sym'])
otp.run(orders)
Time | market_vwap | arrival | exit | sym | |
---|---|---|---|---|---|
0 | 2003-12-01 00:00:00.000 | 160.548890 | 2023-04-10 10:25:59 | 2023-04-10 10:26:07 | AAPL |
1 | 2003-12-01 00:00:00.001 | 286.136779 | 2023-04-10 10:26:09 | 2023-04-10 10:27:48 | MSFT |
Point-in-time benchmarks: BBO at different markouts#
Now let’s find the prevailing quote at different time intervals (markouts) before/after each trade.
import onetick.query as otq
s = otp.dt(2023, 3, 8, 10)
e = otp.dt(2023, 3, 9, 10, 0, 1)
markouts = [-1, 1, 5, 10, 60]
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
# change the timestamp so it fits into original time range (required by OneTick)
qte.sink(otq.ModifyQueryTimes(start_time=f'_START_TIME + {m * 1000}',
output_timestamp=f'TIMESTAMP - {m * 1000}',
end_time=f'_END_TIME + {m * 1000}'))
qte_by_markout.append(qte)
trd = otp.join_by_time([trd] + qte_by_markout)
# trd.render()
otp.run(trd, start=s, end=e, symbols='TSLA', apply_times_daily=True)
Time | PRICE | SIZE | ASK_PRICE_-1 | BID_PRICE_-1 | quote_time_-1 | ASK_PRICE_1 | BID_PRICE_1 | quote_time_1 | ASK_PRICE_5 | BID_PRICE_5 | quote_time_5 | ASK_PRICE_10 | BID_PRICE_10 | quote_time_10 | ASK_PRICE_60 | BID_PRICE_60 | quote_time_60 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2023-03-08 10:00:00.014762069 | 181.4250 | 300 | 181.47 | 181.41 | 2023-03-08 09:59:59.002564435 | 181.49 | 181.48 | 2023-03-08 10:00:01.000000000 | 181.15 | 181.04 | 2023-03-08 10:00:05.012557243 | 181.16 | 181.08 | 2023-03-08 10:00:10.000000000 | 180.51 | 180.45 | 2023-03-08 10:01:00.012332497 |
1 | 2023-03-08 10:00:00.014764168 | 181.4400 | 12 | 181.47 | 181.41 | 2023-03-08 09:59:59.002564435 | 181.49 | 181.48 | 2023-03-08 10:00:01.000000000 | 181.15 | 181.04 | 2023-03-08 10:00:05.012557243 | 181.16 | 181.08 | 2023-03-08 10:00:10.000000000 | 180.51 | 180.45 | 2023-03-08 10:01:00.012332497 |
2 | 2023-03-08 10:00:00.014767570 | 181.4400 | 200 | 181.47 | 181.41 | 2023-03-08 09:59:59.002564435 | 181.49 | 181.48 | 2023-03-08 10:00:01.000000000 | 181.15 | 181.04 | 2023-03-08 10:00:05.012557243 | 181.16 | 181.08 | 2023-03-08 10:00:10.000000000 | 180.51 | 180.45 | 2023-03-08 10:01:00.012332497 |
3 | 2023-03-08 10:00:00.014799259 | 181.4500 | 2 | 181.47 | 181.41 | 2023-03-08 09:59:59.002564435 | 181.49 | 181.48 | 2023-03-08 10:00:01.000000000 | 181.15 | 181.04 | 2023-03-08 10:00:05.012557243 | 181.16 | 181.08 | 2023-03-08 10:00:10.000000000 | 180.51 | 180.45 | 2023-03-08 10:01:00.012332497 |
4 | 2023-03-08 10:00:00.015374686 | 181.4400 | 300 | 181.47 | 181.41 | 2023-03-08 09:59:59.002564435 | 181.49 | 181.48 | 2023-03-08 10:00:01.000000000 | 181.15 | 181.04 | 2023-03-08 10:00:05.012557243 | 181.16 | 181.08 | 2023-03-08 10:00:10.000000000 | 180.51 | 180.45 | 2023-03-08 10:01:00.012332497 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
705 | 2023-03-09 10:00:00.956041264 | 183.5899 | 500 | 183.46 | 183.43 | 2023-03-09 09:59:59.911620614 | 183.59 | 183.54 | 2023-03-09 10:00:01.945769144 | 183.65 | 183.57 | 2023-03-09 10:00:05.954673686 | 183.68 | 183.65 | 2023-03-09 10:00:10.872345446 | 183.47 | 183.45 | 2023-03-09 10:01:00.941018616 |
706 | 2023-03-09 10:00:00.967881686 | 183.5800 | 25 | 183.46 | 183.43 | 2023-03-09 09:59:59.963372673 | 183.59 | 183.54 | 2023-03-09 10:00:01.963256371 | 183.66 | 183.57 | 2023-03-09 10:00:05.967652794 | 183.68 | 183.65 | 2023-03-09 10:00:10.872345446 | 183.47 | 183.45 | 2023-03-09 10:01:00.941018616 |
707 | 2023-03-09 10:00:00.978963708 | 183.4718 | 136 | 183.46 | 183.42 | 2023-03-09 09:59:59.971349853 | 183.59 | 183.54 | 2023-03-09 10:00:01.963256371 | 183.66 | 183.57 | 2023-03-09 10:00:05.967652794 | 183.68 | 183.65 | 2023-03-09 10:00:10.872345446 | 183.47 | 183.45 | 2023-03-09 10:01:00.941018616 |
708 | 2023-03-09 10:00:00.983358396 | 183.5500 | 20 | 183.46 | 183.41 | 2023-03-09 09:59:59.983288366 | 183.59 | 183.54 | 2023-03-09 10:00:01.963256371 | 183.66 | 183.57 | 2023-03-09 10:00:05.967652794 | 183.68 | 183.65 | 2023-03-09 10:00:10.872345446 | 183.47 | 183.45 | 2023-03-09 10:01:00.941018616 |
709 | 2023-03-09 10:00:00.990945922 | 183.5650 | 200 | 183.44 | 183.41 | 2023-03-09 09:59:59.988781014 | 183.59 | 183.54 | 2023-03-09 10:00:01.963256371 | 183.66 | 183.57 | 2023-03-09 10:00:05.967652794 | 183.68 | 183.65 | 2023-03-09 10:00:10.872345446 | 183.47 | 183.45 | 2023-03-09 10:01:00.941018616 |
710 rows × 18 columns
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='AMZN',
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:01:00.702788 {'PRICE': 102.685, 'short': 102.55571394019401, 'long': 102.55571526781988, 'buy': 0.0, 'sell': 1.0}
SELL
2023-03-31 14:01:00.715928 {'PRICE': 102.69, 'short': 102.55577296703349, 'long': 102.5557718802702, 'buy': 1.0, 'sell': 0.0}
BUY
..
2023-03-31 14:01:00.859880 {'PRICE': 102.685, 'short': 102.55593452066896, 'long': 102.55593932631618, 'buy': 0.0, 'sell': 1.0}
SELL
..
2023-03-31 14:01:01.362596 {'PRICE': 102.6888, 'short': 102.55619792035449, 'long': 102.5561062237178, 'buy': 1.0, 'sell': 0.0}
BUY
.......................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
2023-03-31 14:02:37.925538 {'PRICE': 102.51, 'short': 102.58265328102567, 'long': 102.58265371464864, '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=otp.dt(2023,4,20,9,30), end=otp.dt(2023,4,20,9,35), symbols=['SPY'])
Time | PRICE | UPTICK | |
---|---|---|---|
0 | 2023-04-20 09:30:00.000650240 | 411.2100 | NaN |
1 | 2023-04-20 09:30:00.000656384 | 411.2000 | -1.0 |
2 | 2023-04-20 09:30:00.002436608 | 411.2000 | 0.0 |
3 | 2023-04-20 09:30:00.002562816 | 411.2100 | 1.0 |
4 | 2023-04-20 09:30:00.002568960 | 411.2200 | 1.0 |
... | ... | ... | ... |
17115 | 2023-04-20 09:34:59.781732352 | 411.7400 | 0.0 |
17116 | 2023-04-20 09:34:59.781930752 | 411.7400 | 0.0 |
17117 | 2023-04-20 09:34:59.892375040 | 411.7400 | 0.0 |
17118 | 2023-04-20 09:34:59.930526464 | 411.7425 | 1.0 |
17119 | 2023-04-20 09:34:59.958385152 | 411.7400 | -1.0 |
17120 rows × 3 columns