Alvin3y1 commited on
Commit
3245a32
·
verified ·
1 Parent(s): bbe99a8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +73 -48
app.py CHANGED
@@ -11,7 +11,10 @@ SYMBOL_KRAKEN = "BTC/USD"
11
  PORT = 7860
12
  HISTORY_LENGTH = 300
13
  BROADCAST_RATE = 0.1
14
- DECAY_LAMBDA = 100.0
 
 
 
15
  IMPACT_SENSITIVITY = 0.5
16
 
17
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s')
@@ -20,7 +23,8 @@ market_state = {
20
  "bids": {},
21
  "asks": {},
22
  "history": [],
23
- "pred_history": [],
 
24
  "current_mid": 0.0,
25
  "prev_mid": 0.0,
26
  "ready": False
@@ -32,7 +36,8 @@ def analyze_structure(diff_x, diff_y, current_mid):
32
  if not diff_y or len(diff_y) < 5:
33
  return None
34
 
35
- weighted_imbalance = 0.0
 
36
  prev_vol = 0.0
37
 
38
  for i in range(len(diff_x)):
@@ -42,21 +47,26 @@ def analyze_structure(diff_x, diff_y, current_mid):
42
  marginal_vol = cum_vol - prev_vol
43
  prev_vol = cum_vol
44
 
45
- weight = math.exp(-dist / DECAY_LAMBDA)
46
- weighted_imbalance += marginal_vol * weight
 
 
 
47
 
48
- if weighted_imbalance != 0:
49
- impact = math.sqrt(abs(weighted_imbalance)) * IMPACT_SENSITIVITY
50
- if weighted_imbalance < 0:
51
- impact = -impact
52
- else:
53
- impact = 0.0
54
 
55
- projected_price = current_mid + impact
 
 
 
56
 
57
  return {
58
- "projected": projected_price,
59
- "net_score": weighted_imbalance
 
60
  }
61
 
62
  def process_market_data():
@@ -106,15 +116,20 @@ def process_market_data():
106
 
107
  now = time.time()
108
  if analysis:
109
- if not market_state['pred_history'] or (now - market_state['pred_history'][-1]['t'] > 0.5):
110
- market_state['pred_history'].append({'t': now, 'p': analysis['projected']})
111
- if len(market_state['pred_history']) > HISTORY_LENGTH:
112
- market_state['pred_history'].pop(0)
 
 
 
 
113
 
114
  return {
115
  "mid": mid,
116
  "history": market_state['history'],
117
- "pred_history": market_state['pred_history'],
 
118
  "depth_x": diff_x,
119
  "depth_net": diff_y,
120
  "depth_bids": chart_bids,
@@ -136,6 +151,7 @@ HTML_PAGE = f"""
136
  --text-main: #c5c6c7;
137
  --accent-green: #66fcf1;
138
  --accent-red: #ff3b3b;
 
139
  --border: #2d3842;
140
  }}
141
  body {{ margin: 0; padding: 0; background-color: var(--bg-color); color: var(--text-main); font-family: monospace; overflow: hidden; height: 100vh; width: 100vw; }}
@@ -168,6 +184,7 @@ HTML_PAGE = f"""
168
  .stat-value {{ font-size: 24px; font-weight: bold; }}
169
  .green {{ color: var(--accent-green); }}
170
  .red {{ color: var(--accent-red); }}
 
171
 
172
  #loader {{ position: absolute; top:0; left:0; width:100%; height:100%; background: rgba(0,0,0,0.95); z-index: 999; display: flex; flex-direction: column; justify-content: center; align-items: center; color: var(--accent-green); }}
173
  </style>
@@ -200,12 +217,16 @@ HTML_PAGE = f"""
200
  <div class="panel-header">HFT ANALYTICS ENGINE</div>
201
  <div class="stats-content">
202
  <div class="stat-box">
203
- <span class="stat-label">WEIGHTED IMBALANCE SCORE</span>
204
  <span id="score-val" class="stat-value">0</span>
205
  </div>
206
  <div class="stat-box" style="border: 1px solid #444;">
207
- <span class="stat-label" style="color:var(--accent-green);">IMPACT PROJECTION</span>
208
- <span id="proj-val" class="stat-value">---</span>
 
 
 
 
209
  </div>
210
  </div>
211
  </div>
@@ -218,7 +239,8 @@ HTML_PAGE = f"""
218
  status: document.getElementById('loading-status'),
219
  price: document.getElementById('live-price'),
220
  scoreVal: document.getElementById('score-val'),
221
- projVal: document.getElementById('proj-val')
 
222
  }};
223
 
224
  const chartCommon = {{
@@ -230,28 +252,22 @@ HTML_PAGE = f"""
230
  }};
231
 
232
  const priceChart = LightweightCharts.createChart(document.getElementById('tv-price'), chartCommon);
 
233
  const priceSeries = priceChart.addLineSeries({{ color: '#2962FF', lineWidth: 2, title: 'Price' }});
234
 
235
- const pastPredSeries = priceChart.addLineSeries({{
236
- color: '#555555',
237
- lineWidth: 1,
238
- title: 'Past Prediction'
239
- }});
240
 
241
- const futurePredSeries = priceChart.addLineSeries({{
242
- color: '#ff9800',
243
- lineWidth: 2,
244
- lineStyle: 2,
245
- title: 'Projection'
246
- }});
247
 
248
  const rawChart = LightweightCharts.createChart(document.getElementById('tv-raw'), {{
249
  ...chartCommon,
250
  timeScale: {{ tickMarkFormatter: (time) => parseFloat(time).toFixed(0) }},
251
  localization: {{ timeFormatter: (time) => 'Dist: $' + parseFloat(time).toFixed(2) }}
252
  }});
253
- const rawBidSeries = rawChart.addAreaSeries({{ lineColor: '#00e676', topColor: 'rgba(0, 230, 118, 0.2)', bottomColor: 'rgba(0, 230, 118, 0.0)', lineWidth: 2, title: "Bids" }});
254
- const rawAskSeries = rawChart.addAreaSeries({{ lineColor: '#ff1744', topColor: 'rgba(255, 23, 68, 0.2)', bottomColor: 'rgba(255, 23, 68, 0.0)', lineWidth: 2, title: "Asks" }});
255
 
256
  const netChart = LightweightCharts.createChart(document.getElementById('tv-net'), {{
257
  ...chartCommon,
@@ -295,31 +311,40 @@ HTML_PAGE = f"""
295
  if (!seen.has(t)) {{ seen.add(t); cleanHistory.push({{ time: t, value: d.p }}); }}
296
  }});
297
 
298
- const predHistory = [];
299
- const seenP = new Set();
300
- if(data.pred_history) {{
301
- data.pred_history.forEach(d => {{
 
 
 
 
 
 
 
 
 
302
  const t = Math.floor(d.t);
303
- if(!seenP.has(t)) {{ seenP.add(t); predHistory.push({{ time: t, value: d.p }}); }}
304
  }});
305
  }}
306
 
307
  if (cleanHistory.length) {{
308
  priceSeries.setData(cleanHistory);
309
- pastPredSeries.setData(predHistory);
 
310
 
311
  const last = cleanHistory[cleanHistory.length-1];
312
  dom.price.innerText = last.value.toLocaleString(undefined, {{minimumFractionDigits: 2}});
313
 
314
  if (data.analysis) {{
315
- const {{ projected, net_score }} = data.analysis;
316
 
317
- futurePredSeries.setData([
318
- last,
319
- {{ time: last.time + 60, value: projected }}
320
- ]);
321
 
322
- dom.projVal.innerText = projected.toLocaleString(undefined, {{minimumFractionDigits: 0, maximumFractionDigits: 0}});
 
323
 
324
  dom.scoreVal.innerText = net_score.toFixed(2);
325
  dom.scoreVal.className = net_score > 0 ? "stat-value green" : "stat-value red";
 
11
  PORT = 7860
12
  HISTORY_LENGTH = 300
13
  BROADCAST_RATE = 0.1
14
+
15
+ DECAY_LAMBDA_SHORT = 100.0
16
+ DECAY_LAMBDA_LONG = 500.0
17
+
18
  IMPACT_SENSITIVITY = 0.5
19
 
20
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s')
 
23
  "bids": {},
24
  "asks": {},
25
  "history": [],
26
+ "pred_history_short": [],
27
+ "pred_history_long": [],
28
  "current_mid": 0.0,
29
  "prev_mid": 0.0,
30
  "ready": False
 
36
  if not diff_y or len(diff_y) < 5:
37
  return None
38
 
39
+ w_imbalance_short = 0.0
40
+ w_imbalance_long = 0.0
41
  prev_vol = 0.0
42
 
43
  for i in range(len(diff_x)):
 
47
  marginal_vol = cum_vol - prev_vol
48
  prev_vol = cum_vol
49
 
50
+ weight_short = math.exp(-dist / DECAY_LAMBDA_SHORT)
51
+ w_imbalance_short += marginal_vol * weight_short
52
+
53
+ weight_long = math.exp(-dist / DECAY_LAMBDA_LONG)
54
+ w_imbalance_long += marginal_vol * weight_long
55
 
56
+ if w_imbalance_short != 0:
57
+ impact_s = math.sqrt(abs(w_imbalance_short)) * IMPACT_SENSITIVITY
58
+ if w_imbalance_short < 0: impact_s = -impact_s
59
+ else: impact_s = 0.0
 
 
60
 
61
+ if w_imbalance_long != 0:
62
+ impact_l = math.sqrt(abs(w_imbalance_long)) * IMPACT_SENSITIVITY
63
+ if w_imbalance_long < 0: impact_l = -impact_l
64
+ else: impact_l = 0.0
65
 
66
  return {
67
+ "proj_short": current_mid + impact_s,
68
+ "proj_long": current_mid + impact_l,
69
+ "net_score": w_imbalance_short
70
  }
71
 
72
  def process_market_data():
 
116
 
117
  now = time.time()
118
  if analysis:
119
+ if not market_state['pred_history_short'] or (now - market_state['pred_history_short'][-1]['t'] > 0.5):
120
+ market_state['pred_history_short'].append({'t': now, 'p': analysis['proj_short']})
121
+ if len(market_state['pred_history_short']) > HISTORY_LENGTH:
122
+ market_state['pred_history_short'].pop(0)
123
+
124
+ market_state['pred_history_long'].append({'t': now, 'p': analysis['proj_long']})
125
+ if len(market_state['pred_history_long']) > HISTORY_LENGTH:
126
+ market_state['pred_history_long'].pop(0)
127
 
128
  return {
129
  "mid": mid,
130
  "history": market_state['history'],
131
+ "pred_history_short": market_state['pred_history_short'],
132
+ "pred_history_long": market_state['pred_history_long'],
133
  "depth_x": diff_x,
134
  "depth_net": diff_y,
135
  "depth_bids": chart_bids,
 
151
  --text-main: #c5c6c7;
152
  --accent-green: #66fcf1;
153
  --accent-red: #ff3b3b;
154
+ --accent-purple: #ce93d8;
155
  --border: #2d3842;
156
  }}
157
  body {{ margin: 0; padding: 0; background-color: var(--bg-color); color: var(--text-main); font-family: monospace; overflow: hidden; height: 100vh; width: 100vw; }}
 
184
  .stat-value {{ font-size: 24px; font-weight: bold; }}
185
  .green {{ color: var(--accent-green); }}
186
  .red {{ color: var(--accent-red); }}
187
+ .purple {{ color: var(--accent-purple); }}
188
 
189
  #loader {{ position: absolute; top:0; left:0; width:100%; height:100%; background: rgba(0,0,0,0.95); z-index: 999; display: flex; flex-direction: column; justify-content: center; align-items: center; color: var(--accent-green); }}
190
  </style>
 
217
  <div class="panel-header">HFT ANALYTICS ENGINE</div>
218
  <div class="stats-content">
219
  <div class="stat-box">
220
+ <span class="stat-label">WEIGHTED IMBALANCE (SHORT)</span>
221
  <span id="score-val" class="stat-value">0</span>
222
  </div>
223
  <div class="stat-box" style="border: 1px solid #444;">
224
+ <span class="stat-label" style="color:#aaa;">SHORT TERM TARGET</span>
225
+ <span id="proj-short" class="stat-value">---</span>
226
+ </div>
227
+ <div class="stat-box" style="border: 1px solid #7b1fa2;">
228
+ <span class="stat-label" style="color:var(--accent-purple);">LONG TERM TARGET (CENTER OF MASS)</span>
229
+ <span id="proj-long" class="stat-value purple">---</span>
230
  </div>
231
  </div>
232
  </div>
 
239
  status: document.getElementById('loading-status'),
240
  price: document.getElementById('live-price'),
241
  scoreVal: document.getElementById('score-val'),
242
+ projShort: document.getElementById('proj-short'),
243
+ projLong: document.getElementById('proj-long')
244
  }};
245
 
246
  const chartCommon = {{
 
252
  }};
253
 
254
  const priceChart = LightweightCharts.createChart(document.getElementById('tv-price'), chartCommon);
255
+
256
  const priceSeries = priceChart.addLineSeries({{ color: '#2962FF', lineWidth: 2, title: 'Price' }});
257
 
258
+ const pastShortSeries = priceChart.addLineSeries({{ color: '#555555', lineWidth: 1, title: 'Short Term (Past)' }});
259
+ const futureShortSeries = priceChart.addLineSeries({{ color: '#ff9800', lineWidth: 2, lineStyle: 2, title: 'Short Term (Fut)' }});
 
 
 
260
 
261
+ const pastLongSeries = priceChart.addLineSeries({{ color: '#7b1fa2', lineWidth: 1, title: 'Long Term (Past)' }});
262
+ const futureLongSeries = priceChart.addLineSeries({{ color: '#ce93d8', lineWidth: 2, lineStyle: 2, title: 'Long Term (Fut)' }});
 
 
 
 
263
 
264
  const rawChart = LightweightCharts.createChart(document.getElementById('tv-raw'), {{
265
  ...chartCommon,
266
  timeScale: {{ tickMarkFormatter: (time) => parseFloat(time).toFixed(0) }},
267
  localization: {{ timeFormatter: (time) => 'Dist: $' + parseFloat(time).toFixed(2) }}
268
  }});
269
+ const rawBidSeries = rawChart.addAreaSeries({{ lineColor: '#00e676', topColor: 'rgba(0, 230, 118, 0.2)', bottomColor: 'rgba(0, 230, 118, 0.0)', lineWidth: 2 }});
270
+ const rawAskSeries = rawChart.addAreaSeries({{ lineColor: '#ff1744', topColor: 'rgba(255, 23, 68, 0.2)', bottomColor: 'rgba(255, 23, 68, 0.0)', lineWidth: 2 }});
271
 
272
  const netChart = LightweightCharts.createChart(document.getElementById('tv-net'), {{
273
  ...chartCommon,
 
311
  if (!seen.has(t)) {{ seen.add(t); cleanHistory.push({{ time: t, value: d.p }}); }}
312
  }});
313
 
314
+ const predShort = [];
315
+ const seenS = new Set();
316
+ if(data.pred_history_short) {{
317
+ data.pred_history_short.forEach(d => {{
318
+ const t = Math.floor(d.t);
319
+ if(!seenS.has(t)) {{ seenS.add(t); predShort.push({{ time: t, value: d.p }}); }}
320
+ }});
321
+ }}
322
+
323
+ const predLong = [];
324
+ const seenL = new Set();
325
+ if(data.pred_history_long) {{
326
+ data.pred_history_long.forEach(d => {{
327
  const t = Math.floor(d.t);
328
+ if(!seenL.has(t)) {{ seenL.add(t); predLong.push({{ time: t, value: d.p }}); }}
329
  }});
330
  }}
331
 
332
  if (cleanHistory.length) {{
333
  priceSeries.setData(cleanHistory);
334
+ pastShortSeries.setData(predShort);
335
+ pastLongSeries.setData(predLong);
336
 
337
  const last = cleanHistory[cleanHistory.length-1];
338
  dom.price.innerText = last.value.toLocaleString(undefined, {{minimumFractionDigits: 2}});
339
 
340
  if (data.analysis) {{
341
+ const {{ proj_short, proj_long, net_score }} = data.analysis;
342
 
343
+ futureShortSeries.setData([last, {{ time: last.time + 60, value: proj_short }}]);
344
+ futureLongSeries.setData([last, {{ time: last.time + 300, value: proj_long }}]);
 
 
345
 
346
+ dom.projShort.innerText = proj_short.toLocaleString(undefined, {{minimumFractionDigits: 0, maximumFractionDigits: 0}});
347
+ dom.projLong.innerText = proj_long.toLocaleString(undefined, {{minimumFractionDigits: 0, maximumFractionDigits: 0}});
348
 
349
  dom.scoreVal.innerText = net_score.toFixed(2);
350
  dom.scoreVal.className = net_score > 0 ? "stat-value green" : "stat-value red";