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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +68 -30
app.py CHANGED
@@ -12,8 +12,13 @@ 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
 
@@ -25,6 +30,7 @@ market_state = {
25
  "history": [],
26
  "pred_history_short": [],
27
  "pred_history_long": [],
 
28
  "current_mid": 0.0,
29
  "prev_mid": 0.0,
30
  "ready": False
@@ -36,8 +42,9 @@ def analyze_structure(diff_x, diff_y, current_mid):
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,26 +54,26 @@ def analyze_structure(diff_x, diff_y, current_mid):
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():
@@ -75,8 +82,9 @@ def process_market_data():
75
 
76
  mid = market_state['current_mid']
77
 
78
- raw_bids = sorted(market_state['bids'].items(), key=lambda x: -x[0])[:300]
79
- raw_asks = sorted(market_state['asks'].items(), key=lambda x: x[0])[:300]
 
80
 
81
  d_b_x, d_b_y, cum = [], [], 0
82
  for p, q in raw_bids:
@@ -117,19 +125,27 @@ def process_market_data():
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,
@@ -152,6 +168,7 @@ HTML_PAGE = f"""
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; }}
@@ -185,6 +202,7 @@ HTML_PAGE = f"""
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,7 +235,7 @@ HTML_PAGE = f"""
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;">
@@ -225,9 +243,13 @@ HTML_PAGE = f"""
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>
233
  </div>
@@ -240,7 +262,8 @@ HTML_PAGE = f"""
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 = {{
@@ -255,11 +278,15 @@ HTML_PAGE = f"""
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,
@@ -329,22 +356,33 @@ HTML_PAGE = f"""
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";
 
12
  HISTORY_LENGTH = 300
13
  BROADCAST_RATE = 0.1
14
 
15
+ # --- Tuning Parameters ---
16
+ # Short: Scalping/Spread focus
17
  DECAY_LAMBDA_SHORT = 100.0
18
+ # Long: Swing/Structure focus
19
  DECAY_LAMBDA_LONG = 500.0
20
+ # Macro: Deep Orderbook/Whale focus
21
+ DECAY_LAMBDA_MACRO = 2000.0
22
 
23
  IMPACT_SENSITIVITY = 0.5
24
 
 
30
  "history": [],
31
  "pred_history_short": [],
32
  "pred_history_long": [],
33
+ "pred_history_macro": [],
34
  "current_mid": 0.0,
35
  "prev_mid": 0.0,
36
  "ready": False
 
42
  if not diff_y or len(diff_y) < 5:
43
  return None
44
 
45
+ w_short = 0.0
46
+ w_long = 0.0
47
+ w_macro = 0.0
48
  prev_vol = 0.0
49
 
50
  for i in range(len(diff_x)):
 
54
  marginal_vol = cum_vol - prev_vol
55
  prev_vol = cum_vol
56
 
57
+ # 1. Short Term Decay
58
+ w_short += marginal_vol * math.exp(-dist / DECAY_LAMBDA_SHORT)
59
 
60
+ # 2. Long Term Decay
61
+ w_long += marginal_vol * math.exp(-dist / DECAY_LAMBDA_LONG)
62
+
63
+ # 3. Macro Term Decay
64
+ w_macro += marginal_vol * math.exp(-dist / DECAY_LAMBDA_MACRO)
 
 
65
 
66
+ # Helper for impact calc
67
+ def get_impact(w_imb):
68
+ if w_imb == 0: return 0.0
69
+ imp = math.sqrt(abs(w_imb)) * IMPACT_SENSITIVITY
70
+ return -imp if w_imb < 0 else imp
71
 
72
  return {
73
+ "proj_short": current_mid + get_impact(w_short),
74
+ "proj_long": current_mid + get_impact(w_long),
75
+ "proj_macro": current_mid + get_impact(w_macro),
76
+ "net_score": w_short # We drive the gauge with the short-term pressure
77
  }
78
 
79
  def process_market_data():
 
82
 
83
  mid = market_state['current_mid']
84
 
85
+ # We need a deeper snapshot for Macro analysis
86
+ raw_bids = sorted(market_state['bids'].items(), key=lambda x: -x[0])[:600]
87
+ raw_asks = sorted(market_state['asks'].items(), key=lambda x: x[0])[:600]
88
 
89
  d_b_x, d_b_y, cum = [], [], 0
90
  for p, q in raw_bids:
 
125
  now = time.time()
126
  if analysis:
127
  if not market_state['pred_history_short'] or (now - market_state['pred_history_short'][-1]['t'] > 0.5):
128
+ # Short
129
  market_state['pred_history_short'].append({'t': now, 'p': analysis['proj_short']})
130
  if len(market_state['pred_history_short']) > HISTORY_LENGTH:
131
  market_state['pred_history_short'].pop(0)
132
+
133
+ # Long
134
  market_state['pred_history_long'].append({'t': now, 'p': analysis['proj_long']})
135
  if len(market_state['pred_history_long']) > HISTORY_LENGTH:
136
  market_state['pred_history_long'].pop(0)
137
+
138
+ # Macro
139
+ market_state['pred_history_macro'].append({'t': now, 'p': analysis['proj_macro']})
140
+ if len(market_state['pred_history_macro']) > HISTORY_LENGTH:
141
+ market_state['pred_history_macro'].pop(0)
142
 
143
  return {
144
  "mid": mid,
145
  "history": market_state['history'],
146
  "pred_history_short": market_state['pred_history_short'],
147
  "pred_history_long": market_state['pred_history_long'],
148
+ "pred_history_macro": market_state['pred_history_macro'],
149
  "depth_x": diff_x,
150
  "depth_net": diff_y,
151
  "depth_bids": chart_bids,
 
168
  --accent-green: #66fcf1;
169
  --accent-red: #ff3b3b;
170
  --accent-purple: #ce93d8;
171
+ --accent-cyan: #4dd0e1;
172
  --border: #2d3842;
173
  }}
174
  body {{ margin: 0; padding: 0; background-color: var(--bg-color); color: var(--text-main); font-family: monospace; overflow: hidden; height: 100vh; width: 100vw; }}
 
202
  .green {{ color: var(--accent-green); }}
203
  .red {{ color: var(--accent-red); }}
204
  .purple {{ color: var(--accent-purple); }}
205
+ .cyan {{ color: var(--accent-cyan); }}
206
 
207
  #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); }}
208
  </style>
 
235
  <div class="panel-header">HFT ANALYTICS ENGINE</div>
236
  <div class="stats-content">
237
  <div class="stat-box">
238
+ <span class="stat-label">WEIGHTED IMBALANCE (SCALP)</span>
239
  <span id="score-val" class="stat-value">0</span>
240
  </div>
241
  <div class="stat-box" style="border: 1px solid #444;">
 
243
  <span id="proj-short" class="stat-value">---</span>
244
  </div>
245
  <div class="stat-box" style="border: 1px solid #7b1fa2;">
246
+ <span class="stat-label" style="color:var(--accent-purple);">LONG TERM (SWING)</span>
247
  <span id="proj-long" class="stat-value purple">---</span>
248
  </div>
249
+ <div class="stat-box" style="border: 1px solid #00acc1;">
250
+ <span class="stat-label" style="color:var(--accent-cyan);">MACRO (WHALE)</span>
251
+ <span id="proj-macro" class="stat-value cyan">---</span>
252
+ </div>
253
  </div>
254
  </div>
255
  </div>
 
262
  price: document.getElementById('live-price'),
263
  scoreVal: document.getElementById('score-val'),
264
  projShort: document.getElementById('proj-short'),
265
+ projLong: document.getElementById('proj-long'),
266
+ projMacro: document.getElementById('proj-macro')
267
  }};
268
 
269
  const chartCommon = {{
 
278
 
279
  const priceSeries = priceChart.addLineSeries({{ color: '#2962FF', lineWidth: 2, title: 'Price' }});
280
 
281
+ // Short Term: Show Past + Future Dotted
282
+ const pastShortSeries = priceChart.addLineSeries({{ color: '#555555', lineWidth: 1, title: 'Short (Past)' }});
283
+ const futureShortSeries = priceChart.addLineSeries({{ color: '#ff9800', lineWidth: 2, lineStyle: 2, title: 'Short (Fut)' }});
284
 
285
+ // Long Term: Past Only
286
+ const pastLongSeries = priceChart.addLineSeries({{ color: '#7b1fa2', lineWidth: 1, title: 'Long (Past)' }});
287
+
288
+ // Macro Term: Past Only
289
+ const pastMacroSeries = priceChart.addLineSeries({{ color: '#4dd0e1', lineWidth: 1, title: 'Macro (Past)' }});
290
 
291
  const rawChart = LightweightCharts.createChart(document.getElementById('tv-raw'), {{
292
  ...chartCommon,
 
356
  }});
357
  }}
358
 
359
+ const predMacro = [];
360
+ const seenM = new Set();
361
+ if(data.pred_history_macro) {{
362
+ data.pred_history_macro.forEach(d => {{
363
+ const t = Math.floor(d.t);
364
+ if(!seenM.has(t)) {{ seenM.add(t); predMacro.push({{ time: t, value: d.p }}); }}
365
+ }});
366
+ }}
367
+
368
  if (cleanHistory.length) {{
369
  priceSeries.setData(cleanHistory);
370
  pastShortSeries.setData(predShort);
371
  pastLongSeries.setData(predLong);
372
+ pastMacroSeries.setData(predMacro);
373
 
374
  const last = cleanHistory[cleanHistory.length-1];
375
  dom.price.innerText = last.value.toLocaleString(undefined, {{minimumFractionDigits: 2}});
376
 
377
  if (data.analysis) {{
378
+ const {{ proj_short, proj_long, proj_macro, net_score }} = data.analysis;
379
 
380
+ // Only plot short term future line
381
  futureShortSeries.setData([last, {{ time: last.time + 60, value: proj_short }}]);
 
382
 
383
  dom.projShort.innerText = proj_short.toLocaleString(undefined, {{minimumFractionDigits: 0, maximumFractionDigits: 0}});
384
  dom.projLong.innerText = proj_long.toLocaleString(undefined, {{minimumFractionDigits: 0, maximumFractionDigits: 0}});
385
+ dom.projMacro.innerText = proj_macro.toLocaleString(undefined, {{minimumFractionDigits: 0, maximumFractionDigits: 0}});
386
 
387
  dom.scoreVal.innerText = net_score.toFixed(2);
388
  dom.scoreVal.className = net_score > 0 ? "stat-value green" : "stat-value red";