more cobfixes
This commit is contained in:
@ -4386,11 +4386,11 @@ class DataProvider:
|
||||
# Ensure symbol keys exist in the dictionary with proper deque initialization
|
||||
for sym in ['ETH/USDT', 'BTC/USDT']:
|
||||
if sym not in self.cob_raw_ticks:
|
||||
# Use deque with maxlen for automatic size management (15 min at ~100 ticks/sec)
|
||||
self.cob_raw_ticks[sym] = deque(maxlen=90000)
|
||||
# Use deque with maxlen for automatic size management (30 min at ~100 ticks/sec)
|
||||
self.cob_raw_ticks[sym] = deque(maxlen=180000)
|
||||
if sym not in self.cob_1s_aggregated:
|
||||
# 1s aggregated: 15 minutes = 900 seconds
|
||||
self.cob_1s_aggregated[sym] = deque(maxlen=900)
|
||||
# 1s aggregated: 30 minutes = 1800 seconds
|
||||
self.cob_1s_aggregated[sym] = deque(maxlen=1800)
|
||||
|
||||
# Add to raw ticks - deque automatically handles size limit with maxlen
|
||||
self.cob_raw_ticks[symbol].append(cob_data)
|
||||
@ -4452,7 +4452,7 @@ class DataProvider:
|
||||
elif not isinstance(self.cob_data_cache[symbol], (list, deque)):
|
||||
self.cob_data_cache[symbol] = []
|
||||
self.cob_data_cache[symbol].append(standard_cob_data)
|
||||
if len(self.cob_data_cache[symbol]) > 300: # Keep 5 minutes
|
||||
if len(self.cob_data_cache[symbol]) > 1800: # Keep 30 minutes
|
||||
self.cob_data_cache[symbol].pop(0)
|
||||
|
||||
# Notify subscribers
|
||||
|
@ -341,10 +341,31 @@ def save_inference_audit_image(base_data, model_name: str, symbol: str, out_root
|
||||
ax6 = fig.add_subplot(gs[1, 2])
|
||||
_plot_data_summary(ax6, base_data, symbol)
|
||||
|
||||
# COB data (bottom, spanning all columns)
|
||||
# COB data (bottom, spanning all columns) with optional heatmap overlay above it
|
||||
ax7 = fig.add_subplot(gs[2, :])
|
||||
_plot_cob_data(ax7, prices, bid_v, ask_v, imb, current_price, symbol)
|
||||
|
||||
# Optional: append a small heatmap figure to the side if available
|
||||
try:
|
||||
heat_times = getattr(base_data, 'cob_heatmap_times', [])
|
||||
heat_prices = getattr(base_data, 'cob_heatmap_prices', [])
|
||||
heat_vals = getattr(base_data, 'cob_heatmap_values', [])
|
||||
if heat_times and heat_prices and heat_vals:
|
||||
import numpy as np
|
||||
# Create an inset axes on ax7 for compact heatmap
|
||||
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
|
||||
inset_ax = inset_axes(ax7, width="25%", height="100%", loc='upper right', borderpad=1)
|
||||
z = np.array(heat_vals, dtype=float)
|
||||
if z.size > 0:
|
||||
col_max = np.maximum(z.max(axis=0), 1e-9)
|
||||
zn = (z / col_max).T
|
||||
inset_ax.imshow(zn, aspect='auto', origin='lower', cmap='turbo')
|
||||
inset_ax.set_title('COB Heatmap', fontsize=8)
|
||||
inset_ax.set_xticks([])
|
||||
inset_ax.set_yticks([])
|
||||
except Exception as _hm_ex:
|
||||
logger.debug(f"Audit heatmap overlay skipped: {_hm_ex}")
|
||||
|
||||
# Add overall title with model and timestamp info
|
||||
fig.suptitle(f"{model_name} - {safe_symbol} - {datetime.utcnow().strftime('%H:%M:%S')}",
|
||||
fontsize=14, fontweight='bold')
|
||||
|
@ -1487,6 +1487,70 @@ class CleanTradingDashboard:
|
||||
fig.update_layout(margin=dict(l=10, r=10, t=20, b=10))
|
||||
return fig
|
||||
|
||||
@self.app.callback(
|
||||
Output('cob-heatmap-btc', 'figure'),
|
||||
[Input('interval-component', 'n_intervals')]
|
||||
)
|
||||
def update_cob_heatmap_btc(n):
|
||||
try:
|
||||
times, prices, matrix = [], [], []
|
||||
if hasattr(self.data_provider, 'get_cob_heatmap_matrix'):
|
||||
times, prices, matrix, mids = self.data_provider.get_cob_heatmap_matrix(
|
||||
'BTC/USDT', seconds=300, bucket_radius=10, metric='liquidity'
|
||||
)
|
||||
if not times or not prices or not matrix:
|
||||
fig = go.Figure()
|
||||
fig.add_annotation(text="No COB heatmap data", xref="paper", yref="paper", x=0.5, y=0.5, showarrow=False)
|
||||
fig.update_layout(margin=dict(l=10, r=10, t=20, b=10))
|
||||
return fig
|
||||
z = np.array(matrix, dtype=float)
|
||||
col_max = np.maximum(z.max(axis=0), 1e-9)
|
||||
zn = z / col_max
|
||||
fig = go.Figure(data=go.Heatmap(
|
||||
z=zn.T,
|
||||
x=[t.strftime('%H:%M:%S') for t in times],
|
||||
y=[f"{p:.2f}" for p in prices],
|
||||
colorscale='Turbo',
|
||||
colorbar=dict(title='Norm'),
|
||||
zmin=0.0,
|
||||
zmax=1.0
|
||||
))
|
||||
try:
|
||||
bucket_size = abs(prices[1] - prices[0]) if len(prices) > 1 else 1.0
|
||||
price_line = mids if 'mids' in locals() and mids else []
|
||||
if price_line:
|
||||
y_vals = []
|
||||
y_labels = [float(p) for p in prices]
|
||||
for m in price_line:
|
||||
if m and bucket_size > 0:
|
||||
idx = int(round((m - y_labels[0]) / bucket_size))
|
||||
idx = max(0, min(len(y_labels) - 1, idx))
|
||||
y_vals.append(y_labels[idx])
|
||||
else:
|
||||
y_vals.append(None)
|
||||
fig.add_trace(go.Scatter(
|
||||
x=[t.strftime('%H:%M:%S') for t in times],
|
||||
y=[f"{yv:.2f}" if yv is not None else None for yv in y_vals],
|
||||
mode='lines',
|
||||
line=dict(color='white', width=1.5),
|
||||
name='Mid Price'
|
||||
))
|
||||
except Exception as _line_ex:
|
||||
logger.debug(f"Price line overlay skipped: {_line_ex}")
|
||||
fig.update_layout(
|
||||
title="BTC COB Heatmap (liquidity, per-bucket normalized)",
|
||||
xaxis_title="Time",
|
||||
yaxis_title="Price",
|
||||
margin=dict(l=10, r=10, t=30, b=10)
|
||||
)
|
||||
return fig
|
||||
except Exception as e:
|
||||
logger.error(f"Error rendering BTC COB heatmap: {e}")
|
||||
fig = go.Figure()
|
||||
fig.add_annotation(text=f"Heatmap Error: {str(e)}", xref="paper", yref="paper", x=0.5, y=0.5, showarrow=False)
|
||||
fig.update_layout(margin=dict(l=10, r=10, t=20, b=10))
|
||||
return fig
|
||||
|
||||
# Original training metrics callback - temporarily disabled for testing
|
||||
# @self.app.callback(
|
||||
# Output('training-metrics', 'children'),
|
||||
|
@ -410,15 +410,18 @@ class DashboardLayoutManager:
|
||||
], style={"width": "38%", "marginLeft": "2%"}),
|
||||
], className="d-flex mb-3"),
|
||||
|
||||
# COB Heatmap (ETH)
|
||||
# Mini COB Heatmaps (ETH and BTC)
|
||||
html.Div([
|
||||
html.Div([
|
||||
html.H6([
|
||||
html.I(className="fas fa-fire me-2"),
|
||||
"ETH/USDT COB Heatmap (last 5m, ±10 buckets)"
|
||||
], className="card-title mb-2"),
|
||||
dcc.Graph(id='cob-heatmap-eth', config={'displayModeBar': False}, style={"height": "300px"})
|
||||
], className="card-body p-2")
|
||||
html.Div([
|
||||
html.H6([html.I(className="fas fa-fire me-2"), "ETH Heatmap"], className="card-title mb-2"),
|
||||
dcc.Graph(id='cob-heatmap-eth', config={'displayModeBar': False}, style={"height": "220px"})
|
||||
], className="card-body p-2", style={"flex": "1"}),
|
||||
html.Div([
|
||||
html.H6([html.I(className="fas fa-fire me-2"), "BTC Heatmap"], className="card-title mb-2"),
|
||||
dcc.Graph(id='cob-heatmap-btc', config={'displayModeBar': False}, style={"height": "220px"})
|
||||
], className="card-body p-2", style={"flex": "1", "marginLeft": "1rem"})
|
||||
], className="d-flex")
|
||||
], className="card"),
|
||||
|
||||
# Second row: Pending Orders (left) and Closed Trades (right)
|
||||
|
Reference in New Issue
Block a user