Alvin3y1 commited on
Commit
69a5bc2
Β·
verified Β·
1 Parent(s): 0bde50b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +64 -55
app.py CHANGED
@@ -29,12 +29,12 @@ HTML_PAGE = f"""
29
  <!DOCTYPE html>
30
  <html>
31
  <head>
32
- <title>BTC-USD Mean Pressure</title>
33
  <script src="https://cdn.plot.ly/plotly-2.24.1.min.js"></script>
34
  <style>
35
  body {{ margin: 0; padding: 0; background-color: #0e0e0e; color: #ccc; font-family: sans-serif; overflow: hidden; }}
36
 
37
- /* Layout Grid - 2 Rows x 2 Columns */
38
  #container {{ display: flex; flex-direction: column; height: 100vh; width: 100vw; }}
39
 
40
  /* Rows */
@@ -60,11 +60,9 @@ HTML_PAGE = f"""
60
  <!-- ROW 1 -->
61
  <div class="row">
62
  <div class="col">
63
- <!-- Top Left: Price -->
64
  <div id="price-chart" class="chart"></div>
65
  </div>
66
  <div class="col">
67
- <!-- Top Right: Pressure % -->
68
  <div id="imb-percent-chart" class="chart"></div>
69
  </div>
70
  </div>
@@ -72,11 +70,22 @@ HTML_PAGE = f"""
72
  <!-- ROW 2 -->
73
  <div class="row">
74
  <div class="col">
75
- <!-- Bottom Left: Volume -->
76
  <div id="vol-chart" class="chart"></div>
77
  </div>
78
  <div class="col">
79
- <!-- Bottom Right: Average Pressure (Mean Integral) -->
 
 
 
 
 
 
 
 
 
 
 
 
80
  <div id="mean-chart" class="chart"></div>
81
  </div>
82
  </div>
@@ -86,11 +95,14 @@ HTML_PAGE = f"""
86
  const priceDiv = document.getElementById('price-chart');
87
  const imbPercentDiv = document.getElementById('imb-percent-chart');
88
  const volDiv = document.getElementById('vol-chart');
 
 
89
  const meanDiv = document.getElementById('mean-chart');
90
 
91
  const statusDiv = document.getElementById('status');
92
 
93
- let initPrice = false, initImbP = false, initVol = false, initMean = false;
 
94
 
95
  const commonConfig = {{ responsive: true, displayModeBar: false }};
96
  const commonLayout = {{
@@ -113,48 +125,40 @@ HTML_PAGE = f"""
113
  return;
114
  }}
115
 
116
- statusDiv.innerHTML = `Mid: <span class="${{data.mid >= data.prev_mid ? 'green' : 'red'}}">$${{data.mid.toLocaleString(undefined, {{minimumFractionDigits: 2}})}}</span> | Avg Bias: ${{data.mean.last_val ? data.mean.last_val.toFixed(3) : 0}}`;
117
 
118
  // 1. PRICE HISTORY
119
- if (!initPrice) {{
120
- Plotly.newPlot(priceDiv, [{{ x: data.history.map(d=>new Date(d.t*1000)), y: data.history.map(d=>d.p), type: 'scatter', mode:'lines', line: {{color: '#29b6f6', width: 2}} }}],
121
- {{ ...commonLayout, title: '<b>Midprice</b>', xaxis: {{type:'date', gridcolor:'#222'}} }}, commonConfig);
122
- initPrice = true;
123
- }} else {{
124
- Plotly.react(priceDiv, [{{ x: data.history.map(d=>new Date(d.t*1000)), y: data.history.map(d=>d.p), type: 'scatter', mode:'lines', line: {{color: '#29b6f6', width: 2}} }}],
125
- {{ ...commonLayout, title: '<b>Midprice</b>', xaxis: {{type:'date', gridcolor:'#222'}} }}, commonConfig);
126
- }}
127
 
128
  // 2. IMBALANCE %
 
129
  const layoutImbP = {{ ...commonLayout, title: '<b>Pressure % (-100 to 100)</b>', yaxis: {{range: [-105, 105], gridcolor:'#222'}} }};
130
- if (!initImbP) {{ Plotly.newPlot(imbPercentDiv, [{{ x: data.imbalance_pct.x, y: data.imbalance_pct.y, type: 'scatter', mode: 'lines', fill: 'tozeroy', line: {{color: '#ffeb3b'}} }}], layoutImbP, commonConfig); initImbP = true; }}
131
- else {{ Plotly.react(imbPercentDiv, [{{ x: data.imbalance_pct.x, y: data.imbalance_pct.y, type: 'scatter', mode: 'lines', fill: 'tozeroy', line: {{color: '#ffeb3b'}} }}], layoutImbP, commonConfig); }}
132
 
133
  // 3. VOLUME BY DISTANCE
134
- const layoutVol = {{ ...commonLayout, title: '<b>Volume by Distance</b>' }};
135
  const tracesVol = [
136
  {{ x: data.imbalance_vol.dist_bids, y: data.imbalance_vol.vol_bids, type: 'scatter', name: 'Bid', line: {{color: '#00e676'}} }},
137
  {{ x: data.imbalance_vol.dist_asks, y: data.imbalance_vol.vol_asks, type: 'scatter', name: 'Ask', line: {{color: '#ff1744'}} }}
138
  ];
139
- if (!initVol) {{ Plotly.newPlot(volDiv, tracesVol, layoutVol, commonConfig); initVol = true; }}
140
- else {{ Plotly.react(volDiv, tracesVol, layoutVol, commonConfig); }}
141
-
142
- // 4. MEAN PRESSURE (-1 to +1)
143
- const layoutMean = {{ ...commonLayout,
144
- title: '<b>Average Pressure (Integral / Steps)</b>',
145
- xaxis: {{title: 'Distance ($)', gridcolor:'#222'}},
146
- yaxis: {{title: 'Bias', range: [-1.1, 1.1], gridcolor:'#222', zeroline: true, zerolinecolor: '#fff'}}
147
- }};
148
-
149
- const traceMean = {{
150
- x: data.mean.x,
151
- y: data.mean.y,
152
- type: 'scatter',
153
- mode: 'lines',
154
- fill: 'tozeroy',
155
- line: {{color: '#00bcd4', width: 2}} // Cyan
156
- }};
157
-
158
  if (!initMean) {{ Plotly.newPlot(meanDiv, [traceMean], layoutMean, commonConfig); initMean = true; }}
159
  else {{ Plotly.react(meanDiv, [traceMean], layoutMean, commonConfig); }}
160
 
@@ -241,8 +245,10 @@ async def handle_data(request):
241
 
242
  # --- Calculations ---
243
  imb_x, imb_y = [], []
 
 
244
  mean_x, mean_y = [], []
245
- running_integral = 0
246
 
247
  if d_b_x and d_a_x:
248
  max_dist = min(d_b_x[-1], d_a_x[-1])
@@ -257,31 +263,34 @@ async def handle_data(request):
257
  idx_a = bisect.bisect_right(d_a_x, s)
258
  vol_a = d_a_y[idx_a-1] if idx_a > 0 else 0
259
 
260
- # 2. Imbalance % (-100 to 100)
261
  total_vol = vol_b + vol_a
262
- pct = ((vol_b - vol_a) / total_vol) * 100 if total_vol > 0 else 0
263
 
264
- imb_x.append(s)
265
- imb_y.append(pct)
 
 
 
 
 
266
 
267
- # 3. Mean Pressure
268
- # Integral / Number of Steps
269
- running_integral += pct
270
  step_count = i + 1
271
- mean_pressure = running_integral / step_count
272
-
273
- # Normalize to -1..1 (divide by 100%)
274
- norm_mean = mean_pressure / 100.0
275
-
276
- mean_x.append(s)
277
- mean_y.append(norm_mean)
278
 
279
  return web.json_response({
280
  "mid": mid,
281
  "prev_mid": market_state['history'][-2]['p'] if len(market_state['history']) > 1 else mid,
282
  "imbalance_vol": { "dist_bids": d_b_x, "vol_bids": d_b_y, "dist_asks": d_a_x, "vol_asks": d_a_y },
283
  "imbalance_pct": { "x": imb_x, "y": imb_y },
284
- "mean": { "x": mean_x, "y": mean_y, "last_val": mean_y[-1] if mean_y else 0 },
 
 
285
  "history": market_state['history']
286
  })
287
 
@@ -305,7 +314,7 @@ async def main():
305
  site = web.TCPSite(runner, '0.0.0.0', PORT)
306
  await site.start()
307
 
308
- print(f"πŸš€ BTC-USD Mean Pressure Dashboard: http://localhost:{PORT}")
309
  await asyncio.Event().wait()
310
 
311
  if __name__ == "__main__":
 
29
  <!DOCTYPE html>
30
  <html>
31
  <head>
32
+ <title>BTC-USD 6-Way Analysis</title>
33
  <script src="https://cdn.plot.ly/plotly-2.24.1.min.js"></script>
34
  <style>
35
  body {{ margin: 0; padding: 0; background-color: #0e0e0e; color: #ccc; font-family: sans-serif; overflow: hidden; }}
36
 
37
+ /* Layout Grid - 3 Rows x 2 Columns */
38
  #container {{ display: flex; flex-direction: column; height: 100vh; width: 100vw; }}
39
 
40
  /* Rows */
 
60
  <!-- ROW 1 -->
61
  <div class="row">
62
  <div class="col">
 
63
  <div id="price-chart" class="chart"></div>
64
  </div>
65
  <div class="col">
 
66
  <div id="imb-percent-chart" class="chart"></div>
67
  </div>
68
  </div>
 
70
  <!-- ROW 2 -->
71
  <div class="row">
72
  <div class="col">
 
73
  <div id="vol-chart" class="chart"></div>
74
  </div>
75
  <div class="col">
76
+ <!-- Net Difference (Bids - Asks) -->
77
+ <div id="diff-chart" class="chart"></div>
78
+ </div>
79
+ </div>
80
+
81
+ <!-- ROW 3 -->
82
+ <div class="row">
83
+ <div class="col">
84
+ <!-- Avg Diff (Diff / Steps) -->
85
+ <div id="avg-diff-chart" class="chart"></div>
86
+ </div>
87
+ <div class="col">
88
+ <!-- Mean Pressure (Previous) -->
89
  <div id="mean-chart" class="chart"></div>
90
  </div>
91
  </div>
 
95
  const priceDiv = document.getElementById('price-chart');
96
  const imbPercentDiv = document.getElementById('imb-percent-chart');
97
  const volDiv = document.getElementById('vol-chart');
98
+ const diffDiv = document.getElementById('diff-chart');
99
+ const avgDiffDiv = document.getElementById('avg-diff-chart');
100
  const meanDiv = document.getElementById('mean-chart');
101
 
102
  const statusDiv = document.getElementById('status');
103
 
104
+ let initPrice = false, initImbP = false, initVol = false;
105
+ let initDiff = false, initAvgDiff = false, initMean = false;
106
 
107
  const commonConfig = {{ responsive: true, displayModeBar: false }};
108
  const commonLayout = {{
 
125
  return;
126
  }}
127
 
128
+ statusDiv.innerHTML = `Mid: <span class="${{data.mid >= data.prev_mid ? 'green' : 'red'}}">$${{data.mid.toLocaleString(undefined, {{minimumFractionDigits: 2}})}}</span> | Net Vol: ${{data.diff.last_val ? data.diff.last_val.toFixed(2) : 0}}`;
129
 
130
  // 1. PRICE HISTORY
131
+ const tracePrice = {{ x: data.history.map(d=>new Date(d.t*1000)), y: data.history.map(d=>d.p), type: 'scatter', mode:'lines', line: {{color: '#29b6f6', width: 2}} }};
132
+ if (!initPrice) {{ Plotly.newPlot(priceDiv, [tracePrice], {{ ...commonLayout, title: '<b>Midprice</b>', xaxis: {{type:'date', gridcolor:'#222'}} }}, commonConfig); initPrice = true; }}
133
+ else {{ Plotly.react(priceDiv, [tracePrice], {{ ...commonLayout, title: '<b>Midprice</b>', xaxis: {{type:'date', gridcolor:'#222'}} }}, commonConfig); }}
 
 
 
 
 
134
 
135
  // 2. IMBALANCE %
136
+ const traceImbP = {{ x: data.imbalance_pct.x, y: data.imbalance_pct.y, type: 'scatter', mode: 'lines', fill: 'tozeroy', line: {{color: '#ffeb3b'}} }};
137
  const layoutImbP = {{ ...commonLayout, title: '<b>Pressure % (-100 to 100)</b>', yaxis: {{range: [-105, 105], gridcolor:'#222'}} }};
138
+ if (!initImbP) {{ Plotly.newPlot(imbPercentDiv, [traceImbP], layoutImbP, commonConfig); initImbP = true; }}
139
+ else {{ Plotly.react(imbPercentDiv, [traceImbP], layoutImbP, commonConfig); }}
140
 
141
  // 3. VOLUME BY DISTANCE
 
142
  const tracesVol = [
143
  {{ x: data.imbalance_vol.dist_bids, y: data.imbalance_vol.vol_bids, type: 'scatter', name: 'Bid', line: {{color: '#00e676'}} }},
144
  {{ x: data.imbalance_vol.dist_asks, y: data.imbalance_vol.vol_asks, type: 'scatter', name: 'Ask', line: {{color: '#ff1744'}} }}
145
  ];
146
+ if (!initVol) {{ Plotly.newPlot(volDiv, tracesVol, {{ ...commonLayout, title: '<b>Cumulative Volume</b>' }}, commonConfig); initVol = true; }}
147
+ else {{ Plotly.react(volDiv, tracesVol, {{ ...commonLayout, title: '<b>Cumulative Volume</b>' }}, commonConfig); }}
148
+
149
+ // 4. NET DIFFERENCE (Bids - Asks)
150
+ const traceDiff = {{ x: data.diff.x, y: data.diff.y, type: 'scatter', mode: 'lines', fill: 'tozeroy', line: {{color: '#e040fb'}} }};
151
+ if (!initDiff) {{ Plotly.newPlot(diffDiv, [traceDiff], {{ ...commonLayout, title: '<b>Net Liquidity (Bids - Asks)</b>' }}, commonConfig); initDiff = true; }}
152
+ else {{ Plotly.react(diffDiv, [traceDiff], {{ ...commonLayout, title: '<b>Net Liquidity (Bids - Asks)</b>' }}, commonConfig); }}
153
+
154
+ // 5. AVG NET DIFFERENCE (Diff / Steps)
155
+ const traceAvgDiff = {{ x: data.avg_diff.x, y: data.avg_diff.y, type: 'scatter', mode: 'lines', fill: 'tozeroy', line: {{color: '#ff9800'}} }};
156
+ if (!initAvgDiff) {{ Plotly.newPlot(avgDiffDiv, [traceAvgDiff], {{ ...commonLayout, title: '<b>Density (Net Vol / Step)</b>' }}, commonConfig); initAvgDiff = true; }}
157
+ else {{ Plotly.react(avgDiffDiv, [traceAvgDiff], {{ ...commonLayout, title: '<b>Density (Net Vol / Step)</b>' }}, commonConfig); }}
158
+
159
+ // 6. MEAN PRESSURE (-1 to +1)
160
+ const traceMean = {{ x: data.mean.x, y: data.mean.y, type: 'scatter', mode: 'lines', fill: 'tozeroy', line: {{color: '#00bcd4'}} }};
161
+ const layoutMean = {{ ...commonLayout, title: '<b>Avg Pressure % (-1 to 1)</b>', yaxis: {{range: [-1.1, 1.1], gridcolor:'#222'}} }};
 
 
 
162
  if (!initMean) {{ Plotly.newPlot(meanDiv, [traceMean], layoutMean, commonConfig); initMean = true; }}
163
  else {{ Plotly.react(meanDiv, [traceMean], layoutMean, commonConfig); }}
164
 
 
245
 
246
  # --- Calculations ---
247
  imb_x, imb_y = [], []
248
+ diff_x, diff_y = [], []
249
+ avg_diff_x, avg_diff_y = [], []
250
  mean_x, mean_y = [], []
251
+ running_integral_pct = 0
252
 
253
  if d_b_x and d_a_x:
254
  max_dist = min(d_b_x[-1], d_a_x[-1])
 
263
  idx_a = bisect.bisect_right(d_a_x, s)
264
  vol_a = d_a_y[idx_a-1] if idx_a > 0 else 0
265
 
 
266
  total_vol = vol_b + vol_a
 
267
 
268
+ # 2. Imbalance %
269
+ pct = ((vol_b - vol_a) / total_vol) * 100 if total_vol > 0 else 0
270
+ imb_x.append(s); imb_y.append(pct)
271
+
272
+ # 3. Net Difference (Bids - Asks)
273
+ diff = vol_b - vol_a
274
+ diff_x.append(s); diff_y.append(diff)
275
 
276
+ # 4. Avg Diff (Diff / Steps) -> Density
 
 
277
  step_count = i + 1
278
+ avg_diff = diff / step_count
279
+ avg_diff_x.append(s); avg_diff_y.append(avg_diff)
280
+
281
+ # 5. Mean Pressure (Integral Pct / Steps)
282
+ running_integral_pct += pct
283
+ mean_pressure = (running_integral_pct / step_count) / 100.0 # Normalize -1 to 1
284
+ mean_x.append(s); mean_y.append(mean_pressure)
285
 
286
  return web.json_response({
287
  "mid": mid,
288
  "prev_mid": market_state['history'][-2]['p'] if len(market_state['history']) > 1 else mid,
289
  "imbalance_vol": { "dist_bids": d_b_x, "vol_bids": d_b_y, "dist_asks": d_a_x, "vol_asks": d_a_y },
290
  "imbalance_pct": { "x": imb_x, "y": imb_y },
291
+ "diff": { "x": diff_x, "y": diff_y, "last_val": diff_y[-1] if diff_y else 0 },
292
+ "avg_diff": { "x": avg_diff_x, "y": avg_diff_y },
293
+ "mean": { "x": mean_x, "y": mean_y },
294
  "history": market_state['history']
295
  })
296
 
 
314
  site = web.TCPSite(runner, '0.0.0.0', PORT)
315
  await site.start()
316
 
317
+ print(f"πŸš€ BTC-USD 6-Layer Dashboard: http://localhost:{PORT}")
318
  await asyncio.Event().wait()
319
 
320
  if __name__ == "__main__":