Alvin3y1 commited on
Commit
ad85368
·
verified ·
1 Parent(s): d6d83d7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +47 -47
app.py CHANGED
@@ -100,7 +100,6 @@ def calculate_polr(bids, asks, mid):
100
  """
101
  Path of Least Resistance:
102
  Simulates eating volume on both sides.
103
- Returns the price path where liquidity is thinnest.
104
  """
105
  if not bids or not asks: return []
106
 
@@ -109,9 +108,9 @@ def calculate_polr(bids, asks, mid):
109
 
110
  path_points = []
111
 
112
- # We simulate volume stepping from 0.1 BTC up to 20 BTC
113
- # This represents "Time" or "Intensity" on the X-axis of the projection
114
- volume_steps = [i * 0.5 for i in range(1, 41)] # 0.5, 1.0 ... 20.0
115
 
116
  current_time = time.time()
117
 
@@ -139,29 +138,21 @@ def calculate_polr(bids, asks, mid):
139
  bid_cost_dist = mid - target_bid_price
140
 
141
  # 3. Compare Resistance
142
- # If moving up 10$ costs 5 BTC, but moving down 10$ costs 20 BTC,
143
- # The path of least resistance is UP (it's thinner).
144
-
145
- # Here we compare the DISTANCE moved for the SAME volume.
146
- # If for 5 BTC, Price moves UP $10 and DOWN $2.
147
- # The UP side is "thinner" (less resistance to price change), so price "slips" up.
148
-
149
- projected_p = mid
150
-
151
- # Avoid division by zero or tiny spreads
152
  if bid_cost_dist <= 0: bid_cost_dist = 0.01
153
  if ask_cost_dist <= 0: ask_cost_dist = 0.01
154
 
155
- # Logic: Price goes where the book is thinner (Distance is LARGER for same volume)
156
  if ask_cost_dist > bid_cost_dist:
157
- # It takes LESS liquidity to move UP (Price moved further for same vol)
158
- projected_p = target_ask_price
 
 
 
159
  else:
160
  projected_p = target_bid_price
161
 
162
- # Add slight smoothing/dampening so it connects to current price
163
  path_points.append({
164
- 't': current_time + (i * 2), # Spread points out every 2 seconds into future
165
  'p': projected_p
166
  })
167
 
@@ -400,7 +391,7 @@ HTML_PAGE = f"""
400
 
401
  <div id="p-chart" class="panel">
402
  <div class="chart-header">
403
- PRICE (BLUE) // <span class="c-purp">LEAST RESISTANCE (PURPLE)</span> // <span style="color:var(--yellow)">PRED (YELLOW)</span>
404
  </div>
405
  <div id="tv-price" style="flex: 1; width: 100%;"></div>
406
  </div>
@@ -478,14 +469,33 @@ HTML_PAGE = f"""
478
  }};
479
 
480
  const priceChart = LightweightCharts.createChart(document.getElementById('tv-price'), chartOpts);
481
- const priceSeries = priceChart.addLineSeries({{ color: '#2979ff', lineWidth: 2, title: 'Price' }});
482
 
483
- // Yellow Line: Mathematical Micro-Price
484
- const predSeries = priceChart.addLineSeries({{ color: '#ffeb3b', lineWidth: 2, lineStyle: 2, title: 'Math Forecast' }});
 
 
485
 
486
- // Purple Line: Path of Least Resistance (Lowest Volume)
487
- const polrSeries = priceChart.addLineSeries({{ color: '#d500f9', lineWidth: 3, lineStyle: 0, title: 'Least Resistance' }});
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
488
 
 
 
 
489
  const candleChart = LightweightCharts.createChart(document.getElementById('tv-candles'), {{
490
  ...chartOpts,
491
  timeScale: {{ timeVisible: true, secondsVisible: false }}
@@ -533,19 +543,6 @@ HTML_PAGE = f"""
533
  }}
534
  }}).observe(document.body);
535
 
536
- ['tv-price', 'tv-candles', 'tv-net', 'sidebar-vol', 'sidebar-density'].forEach(id => {{
537
- new ResizeObserver(e => {{
538
- const t = document.getElementById(id);
539
- if (t.clientWidth && t.clientHeight) {{
540
- if(id === 'tv-price') priceChart.applyOptions({{ width: t.clientWidth, height: t.clientHeight }});
541
- if(id === 'tv-candles') candleChart.applyOptions({{ width: t.clientWidth, height: t.clientHeight }});
542
- if(id === 'tv-net') netChart.applyOptions({{ width: t.clientWidth, height: t.clientHeight }});
543
- if(id === 'sidebar-vol') volChart.applyOptions({{ width: t.clientWidth, height: t.clientHeight }});
544
- if(id === 'sidebar-density') denChart.applyOptions({{ width: t.clientWidth, height: t.clientHeight }});
545
- }}
546
- }}).observe(document.getElementById(id));
547
- }});
548
-
549
  function connect() {{
550
  const ws = new WebSocket((location.protocol === 'https:' ? 'wss' : 'ws') + '://' + location.host + '/ws');
551
 
@@ -580,16 +577,19 @@ HTML_PAGE = f"""
580
  dom.score.style.color = rho > 0 ? "var(--green)" : (rho < 0 ? "var(--red)" : "var(--text-main)");
581
  }}
582
 
583
- // 2. Purple Line (Path of Least Resistance)
 
584
  if (data.polr && data.polr.length) {{
585
- // Attach start of POLR to current price to make it seamless
586
- const polrData = [
587
- {{ time: lastTime, value: lastP }},
588
- ...data.polr.map(d => ({{ time: Math.floor(d.t), value: d.p }}))
589
- ];
590
- // Deduplicate times
591
- const uniquePolr = [...new Map(polrData.map(i => [i.time, i])).values()];
592
- polrSeries.setData(uniquePolr);
 
 
593
  }}
594
  }}
595
 
 
100
  """
101
  Path of Least Resistance:
102
  Simulates eating volume on both sides.
 
103
  """
104
  if not bids or not asks: return []
105
 
 
108
 
109
  path_points = []
110
 
111
+ # MODIFIED: Reduced count to 15 distinct lines for performance/clarity
112
+ # Spaced out volume steps to capture depth
113
+ volume_steps = [i * 1.5 for i in range(1, 16)]
114
 
115
  current_time = time.time()
116
 
 
138
  bid_cost_dist = mid - target_bid_price
139
 
140
  # 3. Compare Resistance
 
 
 
 
 
 
 
 
 
 
141
  if bid_cost_dist <= 0: bid_cost_dist = 0.01
142
  if ask_cost_dist <= 0: ask_cost_dist = 0.01
143
 
144
+ projected_p = mid
145
  if ask_cost_dist > bid_cost_dist:
146
+ # UP is harder, Down is easier -> Price goes UP (slip is normally against liquidity, but POLR suggests price follows ease)
147
+ # Actually, conventionally POLR means price goes where resistance is lowest.
148
+ # If Ask side is THICK (High dist), and Bid side is THIN (Low dist), price falls.
149
+ # Logic revised for visualization: We project where price SLIPS to.
150
+ projected_p = target_ask_price
151
  else:
152
  projected_p = target_bid_price
153
 
 
154
  path_points.append({
155
+ 'index': i, # Mark the horizon index
156
  'p': projected_p
157
  })
158
 
 
391
 
392
  <div id="p-chart" class="panel">
393
  <div class="chart-header">
394
+ PRICE (BLUE) // <span class="c-purp">POLR RIVER (PURPLE FADE)</span> // <span style="color:var(--yellow)">PRED (YELLOW)</span>
395
  </div>
396
  <div id="tv-price" style="flex: 1; width: 100%;"></div>
397
  </div>
 
469
  }};
470
 
471
  const priceChart = LightweightCharts.createChart(document.getElementById('tv-price'), chartOpts);
 
472
 
473
+ // --- POLR RIVER INITIALIZATION ---
474
+ // We create an array of series. Index 0 = Nearest Term, Index N = Long Term
475
+ const polrLines = [];
476
+ const polrCount = 15; // Matches backend
477
 
478
+ for(let i=0; i<polrCount; i++) {{
479
+ // Calculate opacity: Nearest = 1.0, Furthest = 0.1
480
+ const opacity = 1.0 - (i / (polrCount + 2));
481
+ const color = `rgba(213, 0, 249, ${{opacity.toFixed(2)}})`; // Purple fade
482
+
483
+ polrLines.push(
484
+ priceChart.addLineSeries({{
485
+ color: color,
486
+ lineWidth: 1,
487
+ crosshairMarkerVisible: false,
488
+ lastValueVisible: false,
489
+ priceLineVisible: false,
490
+ title: ''
491
+ }})
492
+ );
493
+ }}
494
+ // --------------------------------
495
 
496
+ const priceSeries = priceChart.addLineSeries({{ color: '#2979ff', lineWidth: 2, title: 'Price' }});
497
+ const predSeries = priceChart.addLineSeries({{ color: '#ffeb3b', lineWidth: 2, lineStyle: 2, title: 'Math Forecast' }});
498
+
499
  const candleChart = LightweightCharts.createChart(document.getElementById('tv-candles'), {{
500
  ...chartOpts,
501
  timeScale: {{ timeVisible: true, secondsVisible: false }}
 
543
  }}
544
  }}).observe(document.body);
545
 
 
 
 
 
 
 
 
 
 
 
 
 
 
546
  function connect() {{
547
  const ws = new WebSocket((location.protocol === 'https:' ? 'wss' : 'ws') + '://' + location.host + '/ws');
548
 
 
577
  dom.score.style.color = rho > 0 ? "var(--green)" : (rho < 0 ? "var(--red)" : "var(--text-main)");
578
  }}
579
 
580
+ // 2. Purple River (POLR)
581
+ // We update each line individually based on the received array
582
  if (data.polr && data.polr.length) {{
583
+ // We use .update() here to build the history of the prediction lines
584
+ // corresponding to the current time tick
585
+ data.polr.forEach((point, index) => {{
586
+ if (index < polrLines.length) {{
587
+ polrLines[index].update({{
588
+ time: lastTime,
589
+ value: point.p
590
+ }});
591
+ }}
592
+ }});
593
  }}
594
  }}
595