-
Notifications
You must be signed in to change notification settings - Fork 0
/
monitor.py
172 lines (149 loc) · 5.77 KB
/
monitor.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
from collections import deque
import pickle
import dash
from plotly.graph_objs import Table, Scatter
from plotly.subplots import make_subplots
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import redis
import pandas as pd
from config import pairs
# set up dash
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
# set up redis, default port/localhost
redis_conn = redis.StrictRedis()
# params for the dashboard
interval = 1
graph_len = int(0.5 * 60 * 60 // interval)
lob_depth = 10
graph_specs = [
[{"type": "scatter"} for _ in pairs]
]
table_specs = [
[{"type": "table"} for _ in pairs]
]
def add_dash():
"""Create dash layout for each pair with their order book table/historical
spreads. Attach the callbacks for each table/graph separately with their own
subscribe method to call the respective publisher by pair and attributes.
Returns
-------
None
"""
components = [
html.Div(id='spreads_plotly'),
dcc.Interval(
id='tables-update',
interval=interval * 1000,
n_intervals=0
)
]
app.layout = html.Div(children=components)
timestamps_queue = {pair: deque(maxlen=graph_len) for pair in pairs}
spreads_queue = {pair: deque(maxlen=graph_len) for pair in pairs}
def init_callback(app):
"""Dash callback functions matched based on ids to update Dash objects
from data added to Redis.
"""
@app.callback(
Output('spreads_plotly', 'children'),
[Input('tables-update', 'n_intervals')]
)
def update_quotes_balances_plotly(n):
"""Get the dict objects from Redis memory and update Plotly Table,
where each table has a unique id based on its pair. The callback
collects spreads/order book data from Redis memory, so any update
will be updated per interval specified in config.
"""
fig_quotes = make_subplots(
rows=1,
cols=len(pairs),
subplot_titles=pairs,
specs=table_specs
)
fig_hist_spreads = make_subplots(
rows=1,
cols=len(pairs),
specs=graph_specs,
)
for idx, pair in enumerate(pairs):
params = pickle.loads(redis_conn.hget(pair, f'{pair}_spread'))
# convert dict objects into arrays for plotly tables.
exchange_ts = params[f'{pair}_exchange_ts']
spreads = params[f'{pair}_spread']
lob = params[f'{pair}_orderbook']
lob_d = dict(bids_price=list(), bids_quantity=list(),
asks_price=list(), asks_quantity=list())
# limit depth number for displaying order book.
for i, (bids, asks) in enumerate(
zip(lob['bids'].items(), lob['asks'].items())):
lob_d['bids_price'].append(round(float(bids[0]), 4))
lob_d['bids_quantity'].append(round(float(bids[1]), 4))
lob_d['asks_price'].append(round(float(asks[0]), 4))
lob_d['asks_quantity'].append(round(float(asks[1]), 4))
if i >= lob_depth - 1:
break
lob_d = pd.DataFrame(lob_d)
timestamps_queue[pair].append(exchange_ts)
spreads_queue[pair].append(spreads)
fig_quotes.add_trace(
Table(
header=dict(
values=[f'bids_price', f'bids_quantity',
f'asks_price', f'asks_quantity'],
line_color='darkslategray',
fill_color='royalblue',
align='center',
font=dict(color='white', size=8),
),
cells=dict(
values=list(lob_d.T.values),
line_color='darkslategray',
fill_color='white',
align='center',
)
),
row=1, col=idx + 1
)
fig_hist_spreads.add_trace(
Scatter(
x=list(timestamps_queue[pair]),
y=list(spreads_queue[pair]),
name='Historical Spreads',
mode='lines+markers',
marker=dict(color='royalblue')
),
row=1, col=idx + 1
)
fig_quotes.update_layout(
width=1900,
height=300,
showlegend=False,
autosize=True,
font=dict(size=8),
margin=dict(b=0, t=20),
)
fig_hist_spreads.update_layout(
width=1900,
height=300,
showlegend=False,
autosize=True,
font=dict(size=8),
margin=dict(b=0, t=0),
)
dts = [
html.Div([
dcc.Graph(id='quotes', figure=fig_quotes)
]),
html.Div([
dcc.Graph(id='graphs', figure=fig_hist_spreads)
])
]
return dts
init_callback(app=app)
return app
if __name__ == '__main__':
app = add_dash()
app.run_server(debug=False, dev_tools_ui=False, dev_tools_props_check=False)